动画ViewPropertyAnimator使用详解和原理分析

325次阅读  |  发布于2年以前

前言

平常所做的动画大部分是针对View的,而View经常会需要集中动画混合在一起做,因此提供了一个ViewPropertyAnimator类来快速的实现多个动画的混合;

ViewPropertyAnimator从名字就可以看出是专用于View的属性动画,在API12被提供;

ViewPropertyAnimator专用于操作View动画,语法更加简洁,使用更加方便;

今天就来看看怎么用;

一、ViewPropertyAnimator使用详解

1、获取对象

ViewPropertyAnimator 没有构造函数,通过View.animate()方法可以方便的获取;ViewPropertyAnimator 对象,此时获取的动画对象就专用于操作当前view;


public ViewPropertyAnimator animate() {
    if (mAnimator == null) {
        mAnimator = new ViewPropertyAnimator(this);
    }
    return mAnimator;
}

2、基本函数属性介绍

3、基本使用

常用方法

         btnShow.animate()
                        .setDuration(5000)
                        //透明度
                        .alpha(0)
                        .alphaBy(0)
                        //旋转
                        .rotation(360)
                        .rotationBy(360)
                        .rotationX(360)
                        .rotationXBy(360)
                        .rotationY(360)
                        .rotationYBy(360)
                        //缩放
                        .scaleX(1)
                        .scaleXBy(1)
                        .scaleY(1)
                        .scaleYBy(1)
                        //平移
                        .translationX(100)
                        .translationXBy(100)
                        .translationY(100)
                        .translationYBy(100)
                        .translationZ(100)
                        .translationZBy(100)
                        //更改在屏幕上的坐标
                        .x(10)
                        .xBy(10)
                        .y(10)
                        .yBy(10)
                        .z(10)
                        .zBy(10)
                        //监听及其他设置
                        .setInterpolator(new BounceInterpolator())
                        .setStartDelay(1000)
                        .setListener(new Animator.AnimatorListener() {
                            @Override
                            public void onAnimationStart(Animator animation) {
                            }
                            @Override
                            public void onAnimationEnd(Animator animation) {
                            }
                            @Override
                            public void onAnimationCancel(Animator animation) {
                            }
                            @Override
                            public void onAnimationRepeat(Animator animation) {
                            }
                        })
                        .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                            @Override
                            public void onAnimationUpdate(ValueAnimator animation) {
                            }
                        })
                        .withEndAction(new Runnable() {
                            @Override
                            public void run() {
                                Log.i(TAG, "run: end");
                            }
                        })
                        .withStartAction(new Runnable() {
                            @Override
                            public void run() {
                                Log.i(TAG, "run: start");
                            }
                        })
                        .start();

4、添加监听

ViewPropertyAnimator viewPropertyAnimator = gongxiang.animate().setDuration(3000).x(700).y(700).rotation(270).alpha(0.5f).setUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        );
    }
}).setListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationCancel(Animator animation) {
        super.onAnimationCancel(animation);
    }
    @Override
    public void onAnimationEnd(Animator animation) {
        super.onAnimationEnd(animation);
        System.out.println("=========onAnimationEnd=======");
    }
    @Override
    public void onAnimationRepeat(Animator animation) {
        super.onAnimationRepeat(animation);
    }
    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);
        System.out.println("=========onAnimationStart=======");
    }
    @Override
    public void onAnimationPause(Animator animation) {
        super.onAnimationPause(animation);
    }
    @Override
    public void onAnimationResume(Animator animation) {
        super.onAnimationResume(animation);
    }
});

二、基本原理

1、执行动画基本步骤如下

2、startAnimation()的源码


/**
 * Starts the underlying Animator for a set of properties. We use a single animator that
 * simply runs from 0 to 1, and then use that fractional value to set each property
 * value accordingly.
 */
private void startAnimation() {
    if (mRTBackend != null && mRTBackend.startAnimation(this)) {
        return;
    }
    mView.setHasTransientState(true);
    //创建ValueAnimator
    ValueAnimator animator = ValueAnimator.ofFloat(1.0f);
    //clone一份mPendingAnimations赋值给nameValueList
    ArrayList<NameValuesHolder> nameValueList =
            (ArrayList<NameValuesHolder>) mPendingAnimations.clone();
     //赋值完后清空
    mPendingAnimations.clear();
    //用于标识要执行动画的属性
    int propertyMask = 0;
    int propertyCount = nameValueList.size();
    //遍历所有nameValuesHolder,取出其属性名称mNameConstant,
    //执行"|"操作并最终赋值propertyMask
    for (int i = 0; i < propertyCount; ++i) {
        NameValuesHolder nameValuesHolder = nameValueList.get(i);
        propertyMask |= nameValuesHolder.mNameConstant;
    }
    //创建PropertyBundle,并添加到mAnimatorMap中
    mAnimatorMap.put(animator, new PropertyBundle(propertyMask, nameValueList));
    if (mPendingSetupAction != null) {
        //设置硬件加速
        mAnimatorSetupMap.put(animator, mPendingSetupAction);
        mPendingSetupAction = null;
    }
    if (mPendingCleanupAction != null) {
       //移除硬件加速
        mAnimatorCleanupMap.put(animator, mPendingCleanupAction);
        mPendingCleanupAction = null;
    }
    if (mPendingOnStartAction != null) {
        //设置开始的动画(监听器的开始方法中调用)
        mAnimatorOnStartMap.put(animator, mPendingOnStartAction);
        mPendingOnStartAction = null;
    }
    if (mPendingOnEndAction != null) {
        //设置结束后要进行的下一个动画(监听器的结束方法中调用)
        mAnimatorOnEndMap.put(animator, mPendingOnEndAction);
        mPendingOnEndAction = null;
    }
    //添加内部监听器
    animator.addUpdateListener(mAnimatorEventListener);
    animator.addListener(mAnimatorEventListener);
    //判断是否延长开始
    if (mStartDelaySet) {
        animator.setStartDelay(mStartDelay);
    }
    //执行动画的实现
    if (mDurationSet) {
        animator.setDuration(mDuration);
    }
    //设置插值器
    if (mInterpolatorSet) {
        animator.setInterpolator(mInterpolator);
    }
    //开始执行动画
    animator.start();
}

2、PropertyBundle

private static class PropertyBundle {
        int mPropertyMask;
        ArrayList<NameValuesHolder> mNameValuesHolder;
        PropertyBundle(int propertyMask, ArrayList<NameValuesHolder> nameValuesHolder) {
            mPropertyMask = propertyMask;
            mNameValuesHolder = nameValuesHolder;
        }
        boolean cancel(int propertyConstant) {
            if ((mPropertyMask & propertyConstant) != 0 && mNameValuesHolder != null) {
                int count = mNameValuesHolder.size();
                for (int i = 0; i < count; ++i) {
                    NameValuesHolder nameValuesHolder = mNameValuesHolder.get(i);
                    if (nameValuesHolder.mNameConstant == propertyConstant) {
                        mNameValuesHolder.remove(i);
                        mPropertyMask &= ~propertyConstant;
                        return true;
                    }
                }
            }
            return false;
        }
    }

3、AnimatorEventListener

  private class AnimatorEventListener
            implements Animator.AnimatorListener, ValueAnimator.AnimatorUpdateListener {
...
...
}

4、mAnimatorMap

private HashMap<Animator, PropertyBundle> mAnimatorMap =
        new HashMap<Animator, PropertyBundle>();

5、onAnimationUpdate

@Override
        public void onAnimationUpdate(ValueAnimator animation) {
        //取出当前Animator对应用propertyBundle对象
            PropertyBundle propertyBundle = mAnimatorMap.get(animation);
            if (propertyBundle == null) {
                // Shouldn't happen, but just to play it safe
                return;
            }
        //是否开启了硬件加速
            boolean hardwareAccelerated = mView.isHardwareAccelerated();
            // alpha requires slightly different treatment than the other (transform) properties.
            // The logic in setAlpha() is not simply setting mAlpha, plus the invalidation
            // logic is dependent on how the view handles an internal call to onSetAlpha().
            // We track what kinds of properties are set, and how alpha is handled when it is
            // set, and perform the invalidation steps appropriately.
            boolean alphaHandled = false;
            if (!hardwareAccelerated) {
                mView.invalidateParentCaches();
            }
            //取出当前的估算值(插值器计算值)
            float fraction = animation.getAnimatedFraction();
            int propertyMask = propertyBundle.mPropertyMask;
            if ((propertyMask & TRANSFORM_MASK) != 0) {
                mView.invalidateViewProperty(hardwareAccelerated, false);
            }
            //取出所有要执行的属性动画的封装对象NameValuesHolder
            ArrayList<NameValuesHolder> valueList = propertyBundle.mNameValuesHolder;
            if (valueList != null) {
                int count = valueList.size();
                //遍历所有NameValuesHolder,计算变化值,并设置给对应的属性
                for (int i = 0; i < count; ++i) {
                    NameValuesHolder values = valueList.get(i);
                    float value = values.mFromValue + fraction * values.mDeltaValue;
                    if (values.mNameConstant == ALPHA) {
                        alphaHandled = mView.setAlphaNoInvalidation(value);
                    } else {
                        setValue(values.mNameConstant, value);
                    }
                }
            }
            if ((propertyMask & TRANSFORM_MASK) != 0) {
                if (!hardwareAccelerated) {
                    mView.mPrivateFlags |= View.PFLAG_DRAWN; // force another invalidation
                }
            }
            // invalidate(false) in all cases except if alphaHandled gets set to true
            // via the call to setAlphaNoInvalidation(), above
            if (alphaHandled) {
                mView.invalidate(true);
            } else {
                mView.invalidateViewProperty(false, false);
            }
            if (mUpdateListener != null) {
                mUpdateListener.onAnimationUpdate(animation);
            }
        }

总结

年底了,有疫情有裁员,大家要努力,一起加油

Copyright© 2013-2020

All Rights Reserved 京ICP备2023019179号-8