Apply transforms after animating objects on Android
I’m trying to animate a ball image coming into the screen, moving position within the screen and back off-screen. I want to do this in the form of 3 animations; ball_in, ball_shift, and ball_out, and the ability to decide when to move from one animation to another.
This is the code I get so far;
Master .xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<ImageView android:id="@+id/ballImage" xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:layout_margin="5px"
android:src="@drawable/red_ball"
/>
</RelativeLayout>
Primary activity
public class AnimationTest extends Activity
{
AnimationDrawable ballAnimation;
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final ImageView ballImage = (ImageView) findViewById(R.id.ballImage);
final Animation ballOutAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_out);
final Animation ballShiftAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_shift);
ballShiftAnimation.setAnimationListener( new AnimationListener()
{
@Override
public void onAnimationEnd(
Animation animation) {
ballImage.startAnimation(ballOutAnimation);
}
@Override
public void onAnimationRepeat(
Animation animation) {}
@Override
public void onAnimationStart(
Animation animation) {}
});
final Animation ballInAnimation = AnimationUtils.loadAnimation(this, R.anim.ball_in);
ballInAnimation.setAnimationListener( new AnimationListener()
{
@Override
public void onAnimationEnd(
Animation animation) {
ballImage.startAnimation(ballShiftAnimation);
}
@Override
public void onAnimationRepeat(
Animation animation) {}
@Override
public void onAnimationStart(
Animation animation) {}
});
ballImage.startAnimation(ballInAnimation);
}
}
ball_in.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<translate
android:fromXDelta="150"
android:toXDelta="0"
android:fromYDelta="0"
android:toYDelta="0"
android:duration="2000"
android:startOffset="0"
/>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<translate
android:fromXDelta="0"
android:toXDelta="0"
android:fromYDelta="-150"
android:toYDelta="0"
android:duration="1500"
android:startOffset="500"
/>
</set>
</set>
ball_shift.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<translate
android:fromXDelta="0"
android:toXDelta="130"
android:fromYDelta="0"
android:toYDelta="220"
android:duration="2000"
android:startOffset="0"
android:fillAfter="true"
/>
<scale
android:fromXScale="1.0"
android:toXScale="0.623"
android:fromYScale="1.0"
android:toYScale="0.623"
android:duration="2000"
android:startOffset="0"
android:fillAfter="true"
/>
</set>
ball_out.xml
<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<scale
android:fromXScale="0.623"
android:toXScale="0.623"
android:fromYScale="0.623"
android:toYScale="0.623"
/>
<translate
android:fromXDelta="130"
android:toXDelta="330"
android:duration="2000"
android:startOffset="0"
/>
<set xmlns:android="http://schemas.android.com/apk/res/android" android:interpolator="@android:anim/accelerate_decelerate_interpolator">
<translate
android:fromYDelta="220"
android:toYDelta="370"
android:duration="1900"
android:startOffset="100"
/>
</set>
</set>
I
initially put everything in one long animation, but I wanted to split the animation to be able to stop and continue at a given time in the code. In doing so, I realized that the position of the image was reset back to the starting position when the animation was complete, which of course gave me strange results when splitting the animation.
I tried using fillAfter/fillBefore, which is described as applying transforms after/before the animation process, but they don’t seem to do anything to the image. It will still be reset back to the starting position.
Any help or advice on how to do this applies. Thank you.
Solution
You should use AnimationSet for android is connected programmatically.
It should look like this
AnimationSet anim = new AnimationSet(false);
final Animation ballInAnimation = AnimationUtils.loadAnimation(this,
R.anim.ball_in);
ballInAnimation.setFillBefore(true);
final Animation ballShiftAnimation = AnimationUtils.loadAnimation(this,R.anim.ball_shift);
ballShiftAnimation.setStartOffset(ballInAnimation.getDuration());
final Animation ballOutAnimation = AnimationUtils.loadAnimation(this,R.anim.ball_out);
ballOutAnimation.setStartOffset(ballInAnimation.getDuration()+ ballShiftAnimation.getDuration());
anim.addAnimation(ballInAnimation);
anim.addAnimation(ballShiftAnimation);
anim.addAnimation(ballOutAnimation);
anim.setFillAfter(true);
ballImage.startAnimation(anim);
If the TweenAnimations you defined in the XML are connected correctly, this should work.
Note that this will only work visually, and if you need a clickable View, you should use ValueAnimator instead of animation