在android上设置对象动画后应用转换

时间:2010-11-09 12:40:16

标签: java android eclipse

我正在尝试为进入屏幕的球形图像设置动画,在屏幕内移动位置并返回屏幕。我想以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,这被描述为在动画处理之后/之前应用转换,但它们似乎对图像没有任何作用。它仍然会重新回到起始位置。

有关如何执行此操作的任何帮助或建议都是适用的。感谢。

3 个答案:

答案 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新位置设置为动画结束的位置。这可能不起作用,因为我自己没有测试过,但试一试并告诉我结果。