Applying successive animations to ImageView in Android

14,937

Solution 1

It seems as if the ImageView resets its state and the animation is always the same, instead of starting from the final state of the previous animation.

Precisely! I'm sure there's a use for fillAfter="true", but I haven't figured out the point for it yet.

What you need to do is set up an AnimationListener on each Animation of relevance, and do something in the listener's onAnimationEnd() to actually persist the end state of your animation. I haven't played with ScaleAnimation so I'm not quite sure what the way to "persist the end state" would be. If this were an AlphaAnimation, going from 1.0 to 0.0, you would make the widget INVISIBLE or GONE in onAnimationEnd(), for example.

Solution 2

I've had the same problem and created the following code to easily use different animations. It only supports translation and alpha levels for now as I haven't used scaling, but could easily be extended to support more features.

I reset the scroll and the visibility before starting the animation, but that's just because I needed on/off animations.

And the "doEnd" boolean is there to avoid a stack overflow on the recursion (scrollTo calls onAnimationEnd for some obscure reason...)

private void setViewPos(View view, Animation anim, long time){
    // Get the transformation
    Transformation trans = new Transformation();
    anim.getTransformation(time, trans);

    // Get the matrix values
    float[] values = new float[9];
    Matrix m = trans.getMatrix();
    m.getValues(values);

    // Get the position and apply the scroll
    final float x = values[Matrix.MTRANS_X];
    final float y = values[Matrix.MTRANS_Y];
    view.scrollTo(-(int)x, -(int)y);

    // Show/hide depending on final alpha level
    if (trans.getAlpha() > 0.5){
        view.setVisibility(VISIBLE);
    } else {
        view.setVisibility(INVISIBLE);       
    }
}

private void applyAnimation(final View view, final Animation anim){
    view.scrollTo(0, 0);
    view.setVisibility(VISIBLE);

    anim.setAnimationListener(new AnimationListener(){
        private boolean doEnd = true;

        @Override
        public void onAnimationEnd(Animation animation) {
            if (doEnd){
                doEnd = false;
                setViewPos(view, animation, anim.getStartTime() + anim.getDuration());
            }
        }

        @Override
        public void onAnimationRepeat(Animation animation) {
        }

        @Override
        public void onAnimationStart(Animation animation) {
        }

    });

    view.startAnimation(anim);
}
Share:
14,937
hpique
Author by

hpique

iOS, Android & Mac developer. Founder of Robot Media. @hpique

Updated on June 04, 2022

Comments

  • hpique
    hpique almost 2 years

    I would like to apply successive animations (say ScaleAnimation) to an ImageView showing a resource image. The animation is triggered by a button. For example, I would like to incrementally enlarge an image upon each button click.

    I've set fillAfter="true" on the animation. However, all the animations start from the original state of the ImageView. It seems as if the ImageView resets its state and the animation is always the same, instead of starting from the final state of the previous animation.

    What am I doing wrong?

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    
        Button button = (Button)findViewById(R.id.Button01);
        button.setOnClickListener(new OnClickListener() {
    
            public void onClick(View arg0) {
                animate();
    
            }});
    }
    
    private void animate() {
        ImageView imageView = (ImageView) findViewById(R.id.ImageView01);
    
        ScaleAnimation scale = new ScaleAnimation((float)1.0, (float)1.5, (float)1.0, (float)1.5);
        scale.setFillAfter(true);
        scale.setDuration(500);
        imageView.startAnimation(scale); 
    }
    
  • hpique
    hpique about 14 years
    Thanks CommonsWare. For AlphaAnimation it's pretty simple, but for ScaleAnimation and TranslateAnimation such solution would require a little bit of work. Any ideas on how to handle it? Maybe it involves setImageMatrix?
  • CommonsWare
    CommonsWare about 14 years
    TranslateAnimation requires you to adjust your LayoutParams to affect the change (e.g., alter margins) or possibly move the widget from one parent to another (via removeView() and addView()). ScaleAnimation...again, I haven't used it, so I do not have any particular advice here. Sorry!
  • hpique
    hpique about 14 years
    Thanks again. I was thinking of a more generic solution. Something like asking the animation for its transformation matrix, and then applying such matrix to the view. Unfortunately I can't make it work yet.