【问题标题】:Applying transformation after animating an object on android在 android 上为对象设置动画后应用转换
【发布时间】:2012-09-26 05:25:06
【问题描述】:

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

任何有关如何执行此操作的帮助或建议都将得到重视。谢谢。

【问题讨论】:

  • 我不得不承认,我对你提出问题的方式印象深刻。我认为这是我第一次看到有人将他的第一个问题格式化和表述得那么好。为此 +1!

标签: java android eclipse


【解决方案1】:

您应该使用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 已正确连接,这应该可以工作。 请注意,这只会在视觉上起作用,如果您需要可点击视图,则应使用 ValueAnimator 而不是动画

【讨论】:

    【解决方案2】:

    Hacky,但您可以获得最终转换并将其应用于您的 ImageView。我还没有测试实际应用返回的矩阵,但反射代码工作得很好。

    @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)属性,而不是对对象的表示进行动画处理(这是“旧”平移和缩放动画所做的)。

    【讨论】:

      【解决方案3】:

      这可能不是最优雅的解决方案,也可能不起作用,但值得一试。

      onAnimationEnd() 方法中调用下一个动画之前,请尝试使用setFrame() 方法将ImageViews 的新位置设置为动画结束的位置。这可能行不通,因为我自己没有测试过,但试一试并告诉我结果。

      【讨论】:

      • 看到 setFrame() 是一个受保护的方法,我不能在我的视图中显式调用它。我尝试了其他一些解决方法,特别是关于这个主题的最后一个答案; stackoverflow.com/questions/2563941/… 虽然,它似乎在进行转换,但是裁剪图像,我仍然无法进行缩放。
      • @Avilan:该死的......你是对的。没注意,抱歉。
      猜你喜欢
      • 2013-11-13
      • 2015-05-27
      • 2020-04-29
      • 2016-11-01
      • 2015-02-13
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-08-22
      相关资源
      最近更新 更多