动画 - 为什么applyTransformation仅在向一个方向动画时调用?

时间:2014-11-10 18:16:24

标签: android android-animation android-view

这是动画:

public class WidthAnimation extends Animation {

    protected final int originalWidth;
    protected final View view;
    protected float perValue;

    public WidthAnimation(View view, int fromWidth, int toWidth) {
        this.view = view;
        this.originalWidth = fromWidth;
        this.perValue = (toWidth - fromWidth);
    }

    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        view.getLayoutParams().width = (int) (originalWidth + perValue * interpolatedTime);
        view.requestLayout();
    }

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

当被调用时(将View设置为零宽度),它可以正常工作:

WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, getWindowWidthInPixels(), 0);
    widthAnim.setDuration(500);
    dashboardContainerView.startAnimation(widthAnim);

但是当被调用时(将View设置为动画显示),不调用applyTransform,并且不显示动画:

WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, 0, getWindowWidthInPixels());
widthAnim.setDuration(500);
dashboardContainerView.startAnimation(widthAnim);

这两种动画都是通过屏幕点击触发的。 getWindowWidthInPixels()方法正常工作。我在SO上看到了其他一些问题,建议在View或其父级上调用invalidate()或requestLayout()可以解决这个问题,但对我来说这些解决方案不起作用。

1 个答案:

答案 0 :(得分:2)

哇,这很奇怪,它会缩小但不会增长。也许Android正在放弃startAnimation调用,因为视图宽度为0.我想一个快速修复方法是在开始增长动画之前将宽度设置为1.

dashboardContainerView.getLayoutParams().width = 1;
WidthAnimation widthAnim = new WidthAnimation(dashboardContainerView, 0, getWindowWidthInPixels());
widthAnim.setDuration(500);
dashboardContainerView.startAnimation(widthAnim);

另一种选择是切换到ObjectAnimator。当我这样做时,我的动画变得更加直截了当。你的看起来像这样:

    ObjectAnimator anim = ObjectAnimator.ofInt(this, "dashboardWidth", fromWidth, toWidth);
    anim.setDuration(500);
    dashboardContainerView.startAnimation(anim);

public void setDashboardWidth(int width) {
    ViewGroup.LayoutParams params = dashboardContainerView.getLayoutParams();
    params.width = width;
    dashboardContainerView.setLayoutParams(params);
}

这是我通常成功使用的模式。在这种情况下,我不必调用requestLayout,但也许setLayoutParams正在这样做。也许你正在使用的getLayoutParams和requestLayout也可以。

无论如何,我真的很喜欢ObjectAnimator,因为它非常简单。您需要注意的一件事是,如果您使用的是ProGuard,则必须确保它不会清除setDashboardWidth方法,因为它不会直接在您的代码中调用。它是从ObjectAnimator中调用的,它使用反射找到方法。因此,方法的确切名称和签名必须与" dashboardWidth"匹配。调用ofInt。中的属性名称。