I am trying to find out how to do png frame-by-frame animation at a good frame rate...
I have a bunch of pngs(probably 1500 png poses) and I need to play them one-by-one (just like a talking app, take tom cat as an example)
I`ve already tried SurfaceView, normal View, AnimationDrawable and also ImageView(with a thread setting the background with a sleep(33)[for a 30fps]), but none of these ways made a good frame rate compared to tom cat on bad CPU phones (like HTC Desire A).
Its also good to say that I've already added Options to set up the in SampleSize for the images, in case it needs more memory or processing speed.
I think the unique way is loading up an amount of pngs , draw on the SurfaceView and while it plays load more pngs and recycle the other bitmaps...
Anyone can help me with that? At least with some code?
Thanks!
here you go... try this... :)
create an XML file like this on ur values folder
<?xml version="1.0" encoding="utf-8"?>
<resources>
<array name="frames">
<item>#drawable/pak1_1</item>
<item>#drawable/pak1_2</item>
<item>#drawable/pak1_3</item>
<item>#drawable/pak1_4</item>
<item>#drawable/pak1_5</item>
</array>
</resources>
Now try this code:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
Resources res = getResources();
TypedArray FrameImages = res.obtainTypedArray(R.array.frames);
animation = new AnimationDrawable();
for (int i = 0; i < 1500; i++) {
Drawable drawable = FrameImages.getDrawable(i);
animation.addFrame(drawable, 33);
}
animation.setOneShot(false);
ImageView imageAnim = (ImageView) findViewById(R.id.img);
imageAnim.setBackgroundDrawable(animation);
// run the start() method later on the UI thread
imageAnim.post(new Starter());
}
class Starter implements Runnable {
public void run() {
animation.start();
}
}
Related
I have layout FrameLayout as a root layout.
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
android:layout_height="match_parent"
>
<ImageView
android:id="#+id/background_image"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="#drawable/init_image"
android:scaleType="centerCrop">
</ImageView>
......
......
</FrameLayout>
I need to change periodically some amount of images in a infinity loop (some condition) so like slideshow.
I have tried to use Handler but when I change I get OutOfMemory error.
I also tried ImageSwitcher but It seems not to work correctly.
Please give an example or advice how to implement it correctly following all design patterns of Android, thx.
Hye there , i was recently searching for this issue and came across a good solution as it doesn't apply automatic density based scaling of the images and use them as they are.
1- Put all your images in res/drawable-nodpi folder, you have to create this folder as it doesn't exist.
2 - Make them automatically change from one to other in an infinite loop.
int images[] = { R.drawable.background_1,
R.drawable.background_2,
R.drawable.background_3,
R.drawable.background_4,
R.drawable.background_5,
R.drawable.background_6,
R.drawable.background_7 }; // i've these images in **res/drawable-nodpi**
Here is the onCreate method
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
imageView = (ImageView) findViewById(R.id.imageView_Animated);
handler.postDelayed(changeImage, 5000); // after every 5secs it will change image.
}
Now here comes the part which handles all changing of images , outside onCreate do this.
Runnable changeImage = new Runnable() {
#Override
public void run() {
if (count >6) {
handler.removeCallbacks(changeImage);
} else {
if (count >= 6)
count = 0;
AlphaAnimation animation1 = new AlphaAnimation(0.5f, 1.0f); //here is a bit of animation for ya ;)
animation1.setDuration(5000);
animation1.setStartOffset(1300); //time for that color effect
animation1.setFillAfter(true);
imageView.startAnimation(animation1);
imageView.setBackgroundResource(images[count++]);
handler.postDelayed(changeImage, 5000);
}
}
};
All done, hope i helped you.
I have an imageview with a default image. Now when I try to click it, I want it to animate that displays 4 frames of images. How could I accomplish this, I tried a simpler approach (more of a dumb approach) by changing the imageresource 4 times, as expected the image changes so fast that the animating image effect is not visible. Any ideas?
I tried this approach:
Gem = (ImageView)v;
Gem.setImageResource(com.example.gems.R.drawable.bd1);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd2);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd3);
Gem.postDelayed(new Runnable() {
public void run() {
Gem.setImageResource(com.example.gems.R.drawable.bd4);
Gem.postDelayed(new Runnable() {
public void run() {
}
}, 500);
}
}, 500);
}
}, 500);
}
}, 500);
It worked, but is there a better way to this without coding too much lines? I have 25 kinds of images and each image has 4 frames.
EDIT:
I tried using xml transition files:
Java file:
Resources res = this.getResources();
Gem = (ImageView)v;
TransitionDrawable transition;
transition = (TransitionDrawable)
res.getDrawable(R.drawable.blue_diamond_animation);
Gem.setImageDrawable(transition);
transition.startTransition(3000);
xml file:
<transition xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="#drawable/bd1"></item>
<item android:drawable="#drawable/bd2"></item>
<item android:drawable="#drawable/bd3"></item>
<item android:drawable="#drawable/bd4"></item>
<item android:drawable="#drawable/invi"></item>
</transition>
This seems to work, but I don't want to draw this images in a transition. I want to change the background in a transition. I tried changing this android:drawable to android:drawable but it doesn't work.
It turns out that there is an exact class for this: AnimationDrawable
Basically, just add frames with the other pictures to use in the animation to the AnimationDrawable object and specify how long they should display using addFrame(Drawable frame, int duration)
Then set the ImageView to display whatever image it should start with and set the background to the AnimationDrawable you just made using setBackgroundDrawable(Animation)
Lastly, start the animation in the onClick listener
EDIT: FOR EXAMPLE
AnimationDrawable ad = new AnimationDrawable();
ad.addFrame(getResources().getDrawable(R.drawable.image1), 100);
ad.addFrame(getResources().getDrawable(R.drawable.image2), 500);
ad.addFrame(getResources().getDrawable(R.drawable.image3), 300);
ImageView iv = (ImageView) findViewById(R.id.img);
iv.setBackgroundDrawable(animation);
And then in your onClick listener, just call ad.start
It depends on what you are trying to accomplish. You have not given enough info to go on
The viewproperty animator is really the easiest thing to use have a look. It can also be used with older API's using nineoldandroids jar (google it)
http://developer.android.com/reference/android/view/ViewPropertyAnimator.html
The ObjectAnimator and ValueAnimator are also available similar and slightly more difficult to implement
http://developer.android.com/reference/android/animation/ObjectAnimator.html
http://developer.android.com/reference/android/animation/ValueAnimator.html
Have a look at the APIdemos in the sample packs there are a few examples mainly using the ValueAnimator.
http://developer.android.com/tools/samples/index.html
There are also Sprites to consider but it is basically a bitmap , you can user the timer obect to choreograph
I have a frame-by-frame animation and I want to set a specific frame when the stop method has been called. I searched a lot but I haven't found what I was serching for.
Does this method exists? Is it possible to do that?
Use this method on your AnimationDrawable: animationDrawable.selectDrawable(index)
Assuming that frame-by-frame means AnimationDrawable given in the background of an ImageView.
Like that (or via xml):
AnimationDrawable animationDrawable = new AnimationDrawable();
animationDrawable.addFrame(drawableFrame1, 0);
animationDrawable.addFrame(drawableFrame2, 1);
animationDrawable.addFrame(drawableFrame3, 2);
animationDrawable.addFrame(drawableFrame4, 3);
iv = new ImageView(this);
iv.setBackgroundDrawable(animationDrawable);
Here is the code to retrieve a given frame and set it to the background of the ImageView
onStop() {
Drawable drawableFrame2 = ((AnimationDrawable)iv.getBackground()).getFrame(2);
iv.setBackgroundDrawable(drawableFrame2);
iv.postInvalidate();
}
hi i want to give animation using only one image in drawable folder means in imageview tag of xml file i increase width and height of same image now i want to animate it in one place
i had the code which uses series of images seved in drawale folder and animate it but i have only 1 image ..pls give any suitable example which uses only 1 image and animate that image using imageview height and width increasing..thanks in adv
below is my code..
final ImageView splashImageView = (ImageView) findViewById(R.id.SplashImageView);
splashImageView.setBackgroundResource(R.drawable.flag);
final AnimationDrawable frameAnimation = (AnimationDrawable)splashImageView.getBackground();
splashImageView.post(new Runnable(){
#Override
public void run() {
frameAnimation.start();
}
});
final SplashScreen sPlashScreen = this;
// The thread to wait for splash screen events
mSplashThread = new Thread(){
#Override
public void run(){
try {
synchronized(this){
// Wait given period of time or exit on touch
wait(5000);
}
}
catch(InterruptedException ex){
}
}
};
mSplashThread.start();
}
Try this:
ScaleAnimation scaler = new ScaleAnimation((float) 0.7, (float) 1.0, (float) 0.7, (float) 1.0);
scaler.setDuration(40);
imageView1.startAnimation(scaler);
"become big and small in one place" usually is called scaling.
I didn't really read it (just googled "android scaling images"), but this forum post might help you out. It seems to have a code tutorial:
http://www.anddev.org/resize_and_rotate_image_-_example-t621.html
I'm working on a game that requires drawing to SurfaceView's
Canvas. I'm using SurfaceHolder to obtain Canvas to draw to, and
perform drawing in a separate thread. Everything I draw displays
correctly except for this one animation.
Here is the animation definition (it is in res/drawable/
my_animation.xml:
and here is how I draw it to the Canvas:
AnimationDrawable ad = (AnimationDrawable)getResources().getDrawable(R.drawable.my_animation);
ad.draw(canvas);
ad.start();
but only the first frame ever appears on the screen.
What am I missing?
Thank you
If I get the reference right, you have to assign your AnimationDrawable to an ImageView as the example from http://developer.android.com/reference/android/graphics/drawable/AnimationDrawable.html demonstrates:
// Load the ImageView that will host the animation and
// set its background to our AnimationDrawable XML resource.
ImageView img = (ImageView)findViewById(R.id.spinning_wheel_image);
img.setBackgroundResource(R.drawable.spin_animation);
// Get the background, which has been compiled to an AnimationDrawable object.
AnimationDrawable frameAnimation = (AnimationDrawable) img.getBackground();
// Start the animation (looped playback by default).
frameAnimation.start()
In your case you did not assign your AnimationDrawable to any view so I suppose that's why it does not get updated. So you have to call AnimationDrawable.getFrame(int) manually.
If you are already using a separate thread why don't you involve also the code for your animation? This would render your code more consistent in my opinion.
Although this is an old question, i run into this problem too and figure out a walkaround, so i just post it here in case anyone searching about.
```java
final AnimationDrawable animationDrawable = ...;
final View v = new View(this) {
#Override
protected void onDraw(Canvas canvas) {
animDrawable.draw(canvas);
}
};
animationDrawable.setCallback(new Callback() {
#Override
public void unscheduleDrawable(Drawable who, Runnable what) {
v.removeCallbacks(what);
}
#Overridew
public void scheduleDrawable(Drawable who, Runnable what, long when) {
v.postDelayed(what, when - SystemClock.uptimeMillis());
}
#Override
public void invalidateDrawable(Drawable who) {
v.postInvalidate();
}
});
```
Animated drawables of all kinds (Transition, etc.) need a Callback to schedule redrawals. As zhang demonstrates, it is a simple interface for posting Runnables.
To support animated drawables in a custom view, you need two things:
pass your View to your animated Drawable's setCallback. Even base View implements Drawable.Callback, so there's no need to write your own wrapper.
override verifyDrawable to also return true for your animated Drawable.
As to why anyone would need that - I have just implemented animated drawable support in RecyclerView.ItemDecorations, how cool is that :-)
You are working with Canvas means, you are coding in low level. In low level u have to do everything. working with View (ImageView) means, it is high level.In ImageView already defined in low level on canvas how to deal with AnimationDrawable.
Lars Blumberg's answer is correct but the documentation is incorrect; you also need to take into account this: animation start issue