我正在尝试为进入屏幕的球形图像设置动画,在屏幕内移动位置并返回屏幕。我想以3个动画的形式做到这一点; ball_in,ball_shift和ball_out,以及能够决定何时从一个动画转到另一个动画。
这是我到目前为止的代码;
main.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>
主要活动
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>
我最初在一个长动画中拥有所有内容,但是想要将动画分开以便能够在代码中的给定时间停止并继续。这样,我意识到当动画结束时图像的位置被重置回起始位置,这当然在分割动画时给了我奇怪的结果。
我尝试使用fillAfter / fillBefore,这被描述为在动画处理之后/之前应用转换,但它们似乎对图像没有任何作用。它仍然会重新回到起始位置。
有关如何执行此操作的任何帮助或建议都是适用的。感谢。
答案 0 :(得分:3)
您应该使用AnimationSet以编程方式在android中连接动画。 它应该看起来像这样
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);
如果XML中定义的TweenAnimations已正确连接,这应该可以工作。 请注意,这仅适用于VISUALLY,如果您需要视图可点击,则应使用ValueAnimator代替动画
答案 1 :(得分:1)
Hacky,但您可以进行最终转换并将其应用到ImageView
。我还没有测试过实际应用返回的Matrix,但反射代码效果很好。
@Override
public void onAnimationEnd(Animation animation) {
Transformation t = new Transformation();
final float interpolatedTime = animation.getInterpolator().getInterpolation(animation.getDuration());
Class params[] = {Float.TYPE, Transformation.class};
try {
Method m = mAnimationYouWantToGetFinalTransformationFrom.getClass().getDeclaredMethod("applyTransformation", params);
m.setAccessible(true);
m.invoke(mAnimationYouWantToGetFinalTransformationFrom, interpolatedTime, t);
// update object to this final transformation matrix
// For Example: mObjectMatrix = t.getMatrix();
// run your next animation
} // Necessary Catch blocks
对于使用3.0及之后的项目,可以避免此问题。使用ValueAnimator - 动画更新实际对象(在本例中为ballImage)属性,而不是动画对象的表示(这是'旧'翻译和缩放动画的作用)。
答案 2 :(得分:0)
这可能不是最优雅的解决方案,也可能不起作用,但值得一试。
在调用onAnimationEnd()
方法中的下一个动画之前,尝试使用setFrame()方法将ImageViews新位置设置为动画结束的位置。这可能不起作用,因为我自己没有测试过,但试一试并告诉我结果。