Genia S. Genia S. - 3 months ago 10
Android Question

What's the correct way to animate a View from one coordinate to another?

I would like to do the following. I have a set of buttons that have some icons on them. When the user taps one, I would like to introduce a new View that starts in the same coordinate as the tapped icon, and then that new View would shift over to some other location on the screen and when it arrived there be removed.

I know how to create a new view and add/remove it to the parent RelativeLayout (should it not be a RelativeLayout?) and all that. What I'm not clear on is how to get the absolute coordinates of the button that was tapped (since it's just one element inside a parent layout, inside another parent layout) and then set its coordinates and apply an animation, and then what would notify me that it has arrived where it was going, so that I can remove it?

Can't find an example of how to do this anyway, so, hoping someone can point me in the right direction.

Answer

So, it turns out that this is much more straight forward than I imagined.

I created a full screen RelativeLayout that I only show while the animation is happening.

I get the starting position of my burried button like this (it's funny to see these C style coding mechanisms in Java, they're pretty rare these days:

int fromLoc[] = new int[2];
v.getLocationOnScreen(fromLoc);     
float startX = fromLoc[0];
float startY = fromLoc[1];

So, now I have my starting point.

My end point is an absolute coordinate on the screen, you can assign that however you wish

Then I make a little Animations helper class that lets me pass in all the coordinates, the callback, and the duration of the animation

    public class Animations {
public Animation fromAtoB(float fromX, float fromY, float toX, float toY, AnimationListener l, int speed){


        Animation fromAtoB = new TranslateAnimation(
                Animation.ABSOLUTE, //from xType
                fromX, 
                Animation.ABSOLUTE, //to xType
                toX, 
                Animation.ABSOLUTE, //from yType 
                fromY, 
                Animation.ABSOLUTE, //to yType 
                toY
                 );

        fromAtoB.setDuration(speed);
        fromAtoB.setInterpolator(new AnticipateOvershootInterpolator(1.0f));


        if(l != null)
            fromAtoB.setAnimationListener(l);               
                return fromAtoB;
    }
}

and we need a listener to let us know when the animation is done to clear it

 AnimationListener animL = new AnimationListener() {

        @Override
        public void onAnimationStart(Animation animation) {     
        }

        @Override
        public void onAnimationRepeat(Animation animation) {        
        }

        @Override
        public void onAnimationEnd(Animation animation) {
            //this is just a method to delete the ImageView and hide the animation Layout until we need it again.
            clearAnimation();       
        }
    };

And lastly we throw it all together and press GO

int fromLoc[] = new int[2];
    v.getLocationOnScreen(fromLoc);     
    float startX = fromLoc[0];
    float startY = fromLoc[1];      
    RelativeLayout rl = ((RelativeLayout)findViewById(R.id.sticker_animation_layout));
    ImageView sticker = new ImageView(this);

    int stickerId = getStickerIdFromButton(v);
    if(stickerId == 0){
        stickerAnimationPlaying = false;
        return;         
    }

    float destX = 200.0f;//arbitrary place on screen
    float destY = 200.0f;//arbitrary place on screen

    sticker.setBackgroundResource(stickerId);
    sticker.setLayoutParams(new LayoutParams(LayoutParams.WRAP_CONTENT, LayoutParams.WRAP_CONTENT));

    rl.addView(sticker);
    Animations anim = new Animations();
    Animation a = anim.fromAtoB(startX, startY, destX, destY, animL,750);
    sticker.setAnimation(a);
    a.startNow();