I'm creating a gallery view where I'm loading images from the web. While the images are loading, I want to display an animation as a placeholder for each image. I figured this could be done using an AnimationDrawable, however, the animation won't start. The first frame of the animation loads as expected, and if I use the same in for example onWindowFoucsChanged in an activity, everything works fine.
Inside the getView method of my GalleryItemCursorAdapter (which extends SimpleCursorAdapter) I'have the following snippet:
AnimationDrawable frameAnimation = (AnimationDrawable) mContext.getResources().getDrawable(R.drawable.loading);
holder.picture.setImageDrawable(frameAnimation);
frameAnimation.setCallback(holder.picture);
frameAnimation.setVisible(true, true);
frameAnimation.start();
holder.picture is an ImageView. I get no errors, and (very) similar code seems to work fine other places, leading me to believe this may be related to similar to the onCreate issues for animations reported elsewhere. I've tried some variations of the above code, too.
My questions:
Is there an easier/better way to display a loading animation?
What can I do to make the above example work (if at all possible)?
create a new thread and start ..
new Thread(new Runnable() {
public void run(){
// some code that runs outside the ui thread.
frameAnimation.start();
}
}).start();
Related
I'm trying to create an Android app that will include many (sometimes up to about 200) small images that will be animated (relocate and change size) about 20 at a time. After that they'll remain still.
Should I use the simple solution of the View class animation or should I use Drawable animation?
EDIT: I should be more specific..
There are a lot of tutorial out there and a lot of different ways to do the same thing. I'm looking for the best way to implement the next scenario:
Say I have 50 different small (30x30) images currently drawn on the screen.
I need to animate them so they will translate to a different DYNAMIC position. And while they are moving I need the image to be resized up and down (so I get kind of a jump effect if looking from top).
They need to move within a specific timeframe. For example: After the first image starts to move, the second will begin moving 50ms after the last and so on (wave effect)...
After one group of images is translated, another group will be formed, but the last group will still be on screen.
So what I'm asking is a little specifics about the best way to do this. For example: Should I create a XML file for each Image or should I just load them in code? Should I load all the images (there could be up to 200 small images, maybe more) at application start or will it be ok to load them on demand? What would be the best animation technique? Stuff like that.
The easiest solution I found: (API 16+)
Runnable endAction = new Runnable() {
public void run() {
tv.animate().x(400).y(1400).scaleX(1).scaleY(1);
}
};
tv.animate().x(600).y(100).scaleX(3).scaleY(3).withEndAction(endAction);
I would use Drawable animation but it doesn´t matter so much. The important thing you should do if the app runs very slow, is to use diferents threads using this code for example:
Handler mHandler = new Handler();
mHandler.post(new Runnable() {
public void run() {
//YOUR ANIMATION HERE
}
});
In this way, you will be able to process the animation of a lot of images at the same time because the phone will execute the code in different computing threads.
You can use too AsyncTask like that (adding the class into your activity class):
private class doAnimation extends AsyncTask<ImageView, Void, Void>{
#Override
protected Void doInBackground(ImageView... image) {
image.startAnimation(animation);
return null;
}
}
And calling it using:
new doAnimation().execute(image1);
new doAnimation().execute(image2);
new doAnimation().execute(image3);
...
The strangest thing is happening. In my onClick(View ...) I have blocks of code, mostly 'if/else' blocks. The sequence is (in pseudo-code, to save you lengthy code):
I have an image that needs setting using imageButton.setImageResource(randomImage); then
I have a MediaPlayer associated with this image that needs playing, then
I place a sleep(1800) here otherwise the MediaPlayer runs into the next MediaPlayer (this works fine)
This image is compare to another image. If its not the same, then another MediaPlayer named 'boo' is played, and the image that should have been displayed in code 1. above, is replaced by 'flag' image. else //if its the right image then
Switch to 'another' image, play it's corresponding MeidaPlayer, Play a 'cheers' MediaPlayer and change image to a 'tick' image, then do some other logic stuff.
But what is happening is that the code 2. is playing, code 3. is happening. code 4. only the 'boo' mediaplayer is happening and I notice the imagebutton flashing. The image that was supposed to be set in code 1. is delayed and is happening only AFTER the 'boo' mediaplayer. The 'flag' image that replaces the first image setting in code 1. is happening but because code 1. is in delay, what is happening is that the image is not changing (although it is, it's just in delay and then it flashes so quickly that it appears not to change). So code 1. is in delay.
Also, if it goes into the else and the right image is clicked, then the image in code 5. DOES switch to 'another', but the corresponding MeidaPlayer doesn't play, the 'cheers' MediaPlayer doesn't play, the 'tick' image doesn't display, and the other logic doesn't occur. Its as if it is ignoring the code.
What's happening here? Is this a multi-threading situation here? Grouping different parts of the code in their own threads and starting them at once only throws exceptions. Any help will be greatly appreciated!
If you want to delay your code, use Handler.postDelayed(Runnable, long). This won't block the UI thread, and will execute when you want it to.
Whitout your code, it's really unclear what are you trying to achive, and how are you trying to achieve it.
Just to explain Adam's idea.
Put this in your Activity class :
final Handler handler = new Handler();
Runnable _rnbl = new Runnable() {
public void run() {
// Your code
}
};
And call it like this
handler.postDelayed(_rnbl , 5000);
I have a set of 10 images, and I want to create an animation where I cross fade between them. I've been looking into built-in Drawable to achieve such a thing, but no luck on that part.
There is the AnimationDrawable, that switch between pictures, but it doesn't animate the switch.
There is the TransitionDrawable, that cross fade between two pictures, but no more than two.
Hell.
I looked for some solution on Google, but no luck on that part. So I'm thinking about implementing my own drawable to achieve such a thing. Would any of you have any pointers ?
Thanks in advance.
Not sure if you found an answer to this, but I had the same problem and ended up building my own class based on TransitionDrawable.
Usage:
CyclicTransitionDrawable ctd = new CyclicTransitionDrawable(new Drawable[] {
drawable1,
drawable2,
drawable3,
...
});
imageView.setImageDrawable(ctd);
ctd.startTransition(1000, 3000) // 1 second transition, 3 second pause between transitions.
The code for the CyclicTransitionDrawable is available on Github.
Well. Long time has passed, and you probably fixed the issue, but you got setEnterFaceDuration() for AnimationDrawable. Example:
mBackgroundAnimation = new AnimationDrawable();
mBackgroundAnimation.addFrame(getResources().getDrawable(R.drawable.background1), 5000);
// ... rest of the frames
mBackgroundAnimation.addFrame(getResources().getDrawable(R.drawable.background6), 5000);
mBackgroundAnimation.setEnterFadeDuration(1000);
mBackgroundAnimation.setOneShot(false);
With this code you have an easy cycling through 1..N images, each one remains 5s (5000ms) with a fade-in animation. Now, what i do is setting the background of my root RelativeLayout
mLayoutRoot.setBackground(mBackgroundAnimation);
mLayoutRoot.post(new AnimationStarterThread());
And the AnimationStarterThread class
private class AnimationStarterThread implements Runnable {
public void run() {
if(mBackgroundAnimation != null)
mBackgroundAnimation.start();
}
}
I have created an animation drawable and image view in my main game thread which is configured from the activity that handles the game thread (starting it etc.). My code in this handling activity looks like this:
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.one), 1000);
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.two), 1000);
mDistractionsThread.animation.addFrame(getResources().getDrawable(R.drawable.three), 1000);
mDistractionsThread.animation.setOneShot(false);
mDistractionsThread.imageAnim =(ImageView) findViewById(R.id.img);
mDistractionsThread.imageAnim.setBackgroundDrawable(mDistractionsThread.animation);
mDistractionsThread.animation.start();
And as you can see the variable mDistractionsThread is a handle to the thread itself. This compiles fine but only displays the first frame (R.drawable.one) and does not animate at all. What is it I have missed?
I tried to set animation.start() from run() within mDistractionsThread but that just gave me an fatal exception because the View can only be altered from the class that alters its fields - which in this case is not the game thread.
How can I resolve this and get it animating through the frames, and for bonus points, moving across the x-axis?!
Many thanks
It matters where you start the animation. Try starting it in onFocusChanged() in the activity. It should help
I have tried to solve this for days but now i try my luck here.
I use an lazy load to show my images in a custom adaper.
i want to fade in images as they ar download loaded.
This is working BUT the Thread stops while animation is ON
public void run()
{
if(bitmap!=null) {
myProgressBar.setVisibility(View.INVISIBLE);
imageView.setVisibility(View.VISIBLE);
Animation animation = new AlphaAnimation(0.0f,1.0f);
animation.setDuration(800);
imageView.startAnimation(animation);
imageView.setImageBitmap(bitmap);
}else {
myProgressBar.setVisibility(View.VISIBLE);
imageView.setVisibility(View.INVISIBLE);
imageView.setImageResource();
}
what I want to do is to show next row even if the privius animaion not are finished.
Any ides?
This is so because the thread hasn't anything more to execute after the line
imageView.setImageBitmap(bitmap);
is reached.
Although you set a duration of 800 ms, Java doesn't wait on the startAnimation line until this 800 ms are over. If you want to stop your thread after the animation is completed I would recommend to use an AnimationListener to get notified when the animation ends.