Android ObjectAnimato在结束前被取消

时间:2017-05-16 15:00:15

标签: android android-animation objectanimator

我有一个包含3个LinearLayout的片段。默认情况下,第一个权重属性为1。

每个LinearLayout都有OnClickListener触发2个动画:

  • 点击的动画,权重从0到1。
  • 当前打开的动画,权重从1到0。

我的问题是有时动画没有完全完成。

以下是OnClickListener触发的代码:

private void launchAnimation(final LinearLayout llToExpand) {
    ViewWeightAnimationWrapper animationWrapper = new ViewWeightAnimationWrapper(llToExpand);
    ObjectAnimator anim = ObjectAnimator.ofFloat(animationWrapper,
            "weight",
            animationWrapper.getWeight(),
            1f);
    anim.setDuration(1000);

    anim.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d("Anim1", "onAnimationEnd: Anim1 have ended");
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            Log.d("Anim1", "onAnimationCancel: Anim1 have been canceled.");
        }
    });

    ViewWeightAnimationWrapper animationWrapper2 = new ViewWeightAnimationWrapper(mLlCurrentlyOpened);
    ObjectAnimator anim2 = ObjectAnimator.ofFloat(animationWrapper2,
            "weight",
            animationWrapper2.getWeight(),
            0f);
    anim2.setDuration(1000);

    anim2.addListener(new AnimatorListenerAdapter() {
        @Override
        public void onAnimationEnd(Animator animation) {
            Log.d("Anim2", "onAnimationEnd: Anim2 have ended");
            mLlCurrentlyOpened = llToExpand;
        }

        @Override
        public void onAnimationCancel(Animator animation) {
            Log.d("Anim2", "onAnimationCancel: Anim2 have been canceled.");
        }
    });
    anim.start();
    anim2.start();
}

以下是我的ViewWeightAnimationWrapper的代码:

public class ViewWeightAnimationWrapper {
private View view;

public ViewWeightAnimationWrapper(View view) {
    if (view.getLayoutParams() instanceof LinearLayout.LayoutParams) {
        this.view = view;
    } else {
        throw new IllegalArgumentException("The view should be a LinearLayout");
    }
}

public void setWeight(float weight) {
    Log.i(String.valueOf(view.getId()), "setWeight: " + weight);
    LinearLayout.LayoutParams params = (LinearLayout.LayoutParams) view.getLayoutParams();
    params.weight = weight;
    view.requestLayout();
}

public float getWeight() {
    return ((LinearLayout.LayoutParams) view.getLayoutParams()).weight;
}

以下是动画未结束时的日志:

I/2131755212: setWeight: 0.5
I/2131755207: setWeight: 0.5
I/2131755212: setWeight: 0.5251222
I/2131755207: setWeight: 0.47487777
I/2131755212: setWeight: 0.55174345
I/2131755207: setWeight: 0.44825655
D/Anim1: onAnimationCancel: Anim1 have been canceled.
D/Anim1: onAnimationEnd: Anim1 have ended
D/Anim2: onAnimationCancel: Anim2 have been canceled.
D/Anim2: onAnimationEnd: Anim2 have ended

我不知道为什么每次都不取消我的动画。

我如何知道取消动画的内容?是否有可能在取消动画时强制完成动画?

2 个答案:

答案 0 :(得分:0)

我还没有找到动画被取消原因的原因。 在文档中,他们说当在同一个对象上触发相同的动画时动画被取消,这不是我的情况。

但是,我找到了一个解决方法here,它给了我预期的结果。

我已经通过自定义动画替换了ObjectAnimator:

     /**
     * Launch the expand animation on the LinearLayout in parameter and launch the folding animation
     * on the currently opened LinearLayout.
     * @param llToExpand LinearLayout that we want to expand.
     */
    private void launchAnimation(final LinearLayout llToExpand) {

        // Create the and assign the animations
        ExpandAnimation expand = new ExpandAnimation(llToExpand, 0, 1);
        expand.setDuration(500);
        ExpandAnimation fold = new ExpandAnimation(mLlCurrentlyOpened, 1, 0);
        fold.setDuration(500);

        // Start the animations
        llToExpand.startAnimation(expand);
        mLlCurrentlyOpened.startAnimation(fold);

        // Switch the currently opened LinearLayout for the next time
        mLlCurrentlyOpened = llToExpand;
    }

这是我的ExpandAnimation:

public class ExpandAnimation extends Animation {

private float mStartWeight;
private final float mEndWeight;
private final LinearLayout mContent;

public ExpandAnimation(LinearLayout content, float startWeight,
                float endWeight) {
    mStartWeight = startWeight;
    mEndWeight = endWeight;
    mContent = content;
}

@Override
protected void applyTransformation(float interpolatedTime,
                                   Transformation t) {
    LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) mContent
            .getLayoutParams();
    mStartWeight = lp.weight;
    lp.weight = (mStartWeight + ((mEndWeight - mStartWeight) * interpolatedTime));
    mContent.setLayoutParams(lp);
}

@Override
public boolean willChangeBounds() {
    return true;
}
}

答案 1 :(得分:0)

我只是遇到了可能是相同的问题。查看ObjectAnimator源,它持有对动画目标的WeakReference。以我为例,我使用的是创建专门用于执行动画的专用对象,事实证明,弱引用是 only 引用。因此,有时在动画过程中会取消引用它。 ObjectAnimator可以“干净”地处理它,只需取消动画即可。