Android补间动画使用问题

Android · 2023-03-10 · 867 人浏览

设置visibility把View隐藏后再次显示出现旋转中心错误

public RotateAnimation(float fromDegrees, float toDegrees, int pivotXType, float pivotXValue,
        int pivotYType, float pivotYValue) {
    mFromDegrees = fromDegrees;
    mToDegrees = toDegrees;

    mPivotXValue = pivotXValue;
    mPivotXType = pivotXType;
    mPivotYValue = pivotYValue;
    mPivotYType = pivotYType;
    initializePivotPoint();
}

正常情况设置旋转中心为中心点时写法

RotateAnimation anim = new RotateAnimation(0f, 360f, Animation.RELATIVE_TO_SELF, 0.5f, 
                                           Animation.RELATIVE_TO_SELF, 0.5f)

在当前View显示时,设置动画正常播放,如果默认View的状态为GONE,设置动画后在显示后进行播放,会出现旋转中心变成左上角的情况
1.gif
而预期结果是这样的2.gif

深入源码

@Override
public void initialize(int width, int height, int parentWidth, int parentHeight) {
    super.initialize(width, height, parentWidth, parentHeight);
    mPivotX = resolveSize(mPivotXType, mPivotXValue, width, parentWidth);
    mPivotY = resolveSize(mPivotYType, mPivotYValue, height, parentHeight);
}

源码中,根据设置的参数和属性计算出旋转中心的具体值,我们需要看下该方法什么时候调用

/**
 * Utility function, called by draw(canvas, parent, drawingTime) to handle the less common
 * case of an active Animation being run on the view.
 */
private boolean applyLegacyAnimation(ViewGroup parent, long drawingTime,
        Animation a, boolean scalingRequired) {
    Transformation invalidationTransform;
    final int flags = parent.mGroupFlags;
    final boolean initialized = a.isInitialized();
    if (!initialized) {
        a.initialize(mRight - mLeft, mBottom - mTop, parent.getWidth(), parent.getHeight());
        a.initializeInvalidateRegion(0, 0, mRight - mLeft, mBottom - mTop);
        if (mAttachInfo != null) a.setListenerHandler(mAttachInfo.mHandler);
        onAnimationStart();
    }
    ...
}

该方法在View的draw方法进行调用,此时宽高测量完毕,可以准确算出旋转中心的位置
并且有个是否初始化过的前置判断,确保只会触发一次。

public void initialize(int width, int height, int parentWidth, int parentHeight) {
    reset();
    mInitialized = true;
}

一旦初始化,直接更改字段
在未显示时,宽高为0,自然导致旋转中心变成左上角

问题解决

  1. 在设置显示时再讲动画设置进去
  2. 自定义View,在onLayout时手动调用initialize,并将相关参数传入

动画的View在隐藏或者停止后仍残留在屏幕

3.gif
在View消失后,补间动画仍然显示

问题解决

  1. 不要设置setFillAfter属性,否则会残留
  2. 隐藏后手动设置clearAnimation对动画进行清除操作
android 动画
Theme Jasmine by Kent Liao