美文网首页动画
一、Android 动画知识总结(View动画)

一、Android 动画知识总结(View动画)

作者: 徒步青云 | 来源:发表于2020-03-05 12:18 被阅读0次

    动画的意义:
    视觉效果
    引导用户

    一、简介

    Android动画可分为View Animation(视图动画)和Property Animation(属性动画)。
    View Animation包括Tween Animation(补间动画)和Frame Animation(帧动画)。
    Property Animation包括ValueAnimatorObjectAnimator

    在Android系统中,视图动画继承至Animation类,而属性动画继承至Animator类。

    这里先简单介绍一下它们的xml使用方式,让读者有个大致的了解:

    动画类型 存放路径 标签 获取方式 使用方式
    补间动画 res/anim scale、rotate、translate、alpha、set AnimationUtils.loadAnimation() view.startAnimation(anim)
    帧动画 res/drawable animation-list 将drawable作为src或background,然后从View中获取Drawable,并强转成AnimationDrawable AnimationDrawable.start()
    ValueAnimator res/animator animator AnimatorInflater.loadAnimator() start(),然后在AnimatorUpdateListener回调中更新View属性
    ObjectAnimator 同上 objectAnimator 同上 先setTarget(),再start()
    AnimatorSet 同上 set 同上 同上

    二、视图动画

    1、Tween Animation

    顾名思义,补间动画,给出起点、终点、时长、变换方式,系统自动计算出这个过程中所需要的变换。

    Android补间动画主要有以下5种:

    xml标签 java类
    scale SacleAnimation
    alpha AlphaAnimation
    rotate RotateAnimation
    translate TranslateAnimation
    set AnimationSet

    所有动画都继承至Animation,它们都有一些共同的属性:

    xml属性 java方法 解释
    android:duration setDuration(long) 设置动画时长
    android:fillAfter setFillAfter 保持动画结束状态
    android:fillBefore setFillBefore 动画结束时,回到开始状态
    android:repeatCount setRepeatCount 设置重复次数,[整数]/[infinite]
    android:repeatMode setRepeatMode 设置重复模式,[restart]/[reverse]
    android:interpolator setInterpolator(Interpolator) 设置插值器

    其中只有set可以包含多个动画,并让其同时生效,如果需要set中,某个动画延迟运行,可以指定startOffset注意set中repeatCount是无效的,必须对每个动画单独设置才有作用。
    使用方式:

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="@android:integer/config_shortAnimTime"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:shareInterpolator="true" 
        android:fillAfter="true">
        <alpha
            android:fromAlpha="0"
            android:toAlpha="1"
            android:duration="2000" />
        <scale
            android:fromXScale="0"
            android:fromYScale="0"
            android:pivotX="50%p"
            android:pivotY="50%p"
            android:toXScale="1.4"
            android:toYScale="1.4"
            android:duration="2000" />
        <rotate
            android:fromDegrees="0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toDegrees="720"
            android:duration="2000" />
        <translate
            android:fromXDelta="0"
            android:fromYDelta=0"
            android:toXDelta="-80"
            android:toYDelta="-80"
            android:duration="2000" />
    </set>
    

    xml的scale、rotate标签中pivotX和pivotY,表示缩放起始点坐标,可以是数值、百分数、百分数p,如50、50%、50%p。

    如果是50,则表示在当前视图的左上角,即原点处加上50px,作为缩放起始点的坐标;
    如果是50%,则表示在当前控件的左上角加上自己宽度的50%做为缩放起始点的坐标。
    如果是50%p,则表示在当前控件的左上角加上父控件宽度的50%做为缩放起始点的坐标。

    当AnimationSet的shareInterpolator为true时,所有的动画都会使用定义的interpolator插值器。

    private void runTweenAnimation(Context context, View target, int resId) {
        Animation anim = AnimationUtils.loadAnimation(context, resId); //java的Animation直接new 
        anim.setAnimationListener(new Animation.AnimationListener() {
            @Override
            public void onAnimationStart(Animation animation) { }
        
            @Override
            public void onAnimationEnd(Animation animation) { }
        
            @Override
            public void onAnimationRepeat(Animation animation) { }
        });
        target.startAnimation(anim);
    }
    

    2、Frame Animation

    也叫帧动画或者逐帧动画,由字面意思可以知道,它类似电影一样,通过逐帧播放,达到动画效果。使用方式如下:

    <?xml version="1.0" encoding="utf-8"?>
    <animation-list xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot=["true" | "false"]>
        <item
            android:drawable=""
            android:duration="" />
        <item
            android:drawable=""
            android:duration="" />
    </animation-list>
    

    android:oneshot:是否是一次性动画,为true则只会执行一次,false则会一直循环 。
    android:drawable:指定此帧动画所对应的图片资源。
    android:duration:此帧动画持续的时间,单位为毫秒。

    将其设置为控件的资源或背景

    <ImageView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="@drawable/anim"
        android:src="@drawable/anim" /
    

    最后通过获取控件的Drawable对象,将其转换成AnimationDrawable并调用start方法,开启动画。

    private void runFrameAnimation(ImageView image) {
        //AnimationDrawable anim = (AnimationDrawable) image.getBackground();
        AnimationDrawable anim = (AnimationDrawable) image.getDrawable();
        anim.start();
    }
    

    小技巧:当知道资源名,但不知道资源 id 时,可通过getResources().getIdentifier(资源名, 资源文件类型, 应用包名)获得。


    3、自定义Animation

    如果系统提供的5种Animation满足不了你的需求,如3D效果,则可以自定义Animation。

    public class Rrotate3DAnimation extends Animation {
        private int mOffsetX;
        private int mOffsetY;
        private Camera mCamera = new Camera();
        private int mRotateY = 30;
    
        @Override
        public void initialize(int width, int height, int parentWidth, int parentHeight) {
            super.initialize(width, height, parentWidth, parentHeight);
            setDuration(2000);
            setFillAfter(true);
            setInterpolator(new BounceInterpolator());
            mOffsetX = width / 2;
            mOffsetY = height / 2;
        }
    
        @Override
        protected void applyTransformation(float interpolatedTime, Transformation t) {
            final Matrix matrix = t.getMatrix();
            mCamera.save();
            mCamera.rotateY(mRotateY * interpolatedTime);
            mCamera.getMatrix(matrix);
            mCamera.restore();
            matrix.preTranslate(mOffsetX, mOffsetY);
            matrix.postTranslate(-mOffsetX, -mOffsetY);
        }
    }
    

    三、属性动画

    属性动画与视图动画的不同之处:

    1、视图动画继承至Animation类,而属性动画继承至Animator类。
    2、视图动画在运行过程中,并没有改变其内部属性(比如触摸区域不会随动画运动而改变)。

    属性动画可以弥补视图动画的不足之处,比如按钮颜色改变动画,视图动画就难以做到。它可以添加以下监听事件:

    animator.addListener(new Animator.AnimatorListener() {
        @Override
        public void onAnimationStart(Animator animation) { }
    
        //执行cancel()后,依旧会回调onAnimationEnd方法
        @Override
        public void onAnimationEnd(Animator animation) { }
    
        @Override
        public void onAnimationCancel(Animator animation) { }
    
        @Override
        public void onAnimationRepeat(Animator animation) { }
    });
    
    animator.addPauseListener(new Animator.AnimatorPauseListener() {
        @Override
        public void onAnimationPause(Animator animation) { }
    
        @Override
        public void onAnimationResume(Animator animation) { }
    });
    

    1、ValueAnimator

    ValueAnimator是属性动画中常用的一个类,它可以不依赖控件而执行,换句话说:它关注值的改变,而不关注控件如何去使用这个值

    1、定义
    通过资源方式去定义:

    定义:res/animator
    <animator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="int"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:startOffset="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:valueType=["floatType" | "intType" | "pathType" | "colorType"]
        android:interpolator=["@android:interpolator/XXX"]/>
    
    获取:
    ValueAnimator anim = (ValueAnimator) AnimationUtils.loadAnimation(context, R.animator.anim);
    

    通过代码方式去定义:

    ValueAnimator anim = ValueAnimator.ofXXX();
    anim.setDuration(1000);
    anim.setRepeatCount(1);
    anim.setRepeatMode(ValueAnimator.REVERSE);
    anim.setStartDelay(100);
    anim.setInterpolator(new LinearInterpolator());
    

    2、使用
    由于ValueAnimator只负责对指定值区间进行动画运算,而不会去执行具体的动画,所有我们需要对运算过程进行监听,然后自己更新控件的属性,已达到动画的效果。

    private void runValueAnimator(ValueAnimator anim) {
        anim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                // 如果是单个属性动画
                XXX value = (XXX) animation.getAnimatedValue();
                // 如果是通过PropertyValuesHolder创建的多个属性的动画
                XXX value = (XXX) animation.getAnimatedValue("propertyName");
                Log.d("TAG", "value = " + value);
            }
        });
        anim.start();
    }
    

    2、ObjectAnimator

    由于ValueAnimator只能对动画的数值进行计算,如果要操作具体的控件,就需要使用监听动画过程,相比补间动画烦琐很多。而ObjectAnimator正是用来弥补这个缺点的。
    ObjectAnimator继承至ValueAnimator,它通过反射来实现对控件属性的改变:

    通过资源方式去定义:

    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="int"
        android:propertyName="string"
        android:repeatCount="int"
        android:repeatMode=["repeat" | "reverse"]
        android:startOffset="int"
        android:valueFrom="float | int | color"
        android:valueTo="float | int | color"
        android:valueType=["floatType" | "intType" | "pathType" | "colorType"]
        android:interpolator=["@android:interpolator/XXX"]/>
    

    获取并使用:

    private void runObjectAnimator(Context context, @AnimatorRes int res, View target) {
        ObjectAnimator anim = (ObjectAnimator) AnimatorInflater.loadAnimator(context, res);
        anim.setTarget(target);
        anim.start();
    }
    

    通过代码方式去定义并使用:

    ObjectAnimator anim = ObjectAnimator.ofXXX(view, "属性", ......);
    anim.setRepeatCount(1);
    anim.setRepeatMode(ValueAnimator.REVERSE);
    anim.setStartDelay(100);
    anim.setInterpolator(new LinearInterpolator());
    animator.start();
    

    ObjectAnimator是通过反射去调用属性的get/set方法,来完成动画效果。
    当且仅当动画只有一个过渡值时,系统才会调用对应属性的get函数来得到动画的初始值。
    当不存在get函数时,则会取动画参数类型的默认值作为初始值,如果无默认值,将会抛出异常。


    3、AnimatorSet

    ValueAnimator和ObjectAnimator只能实现一个动画,假如我们需要运行组合动画,那该怎么办?
    这就需要用到AnimatorSet了。

    通过资源方式去定义:注意:set只能包含objectAnimator标签,不能包含animator标签

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:ordering=["together" | "sequentially"]>
        <objectAnimator
            ......./>
        <objectAnimator
            ......./>
    </set>
    

    调用:

    private void runAnimatorSet(Context context, @AnimatorRes int res, View target) {
        AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(context, res);
        anim.setTarget(target);
        anim.start();
    }
    

    java代码中创建:

    private void runAnimatorSet() {
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofInt(textView1,"BackgroundColor", 0xffff00ff, 0xffffff00,0xffff00ff);
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(textView1,"translationY",0 , 300, 0);
        ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(textView2, "translationY", 0, 400, 0);
        AnimatorSet animatorSet = new AnimatorSet();
        //一起执行
        animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
        animatorSet.setDuration(1000);
        animatorSet.start();
    }
    

    比较两种创建方式可以发现:通过资源文件创建的集合动画,适用于一个控件的组合动画;通过代码创建的集合动画,适用于多个控件的组合动画。

    AnimatorSet包含两个函数:

    //让动画一起播放
    void playTogether(Animator... items)
    //动画依次播放
    void playSequentially(Animator... items)
    //组合动画播放延时
    void setStartDelay(long startDelay)
    

    注意:这里items可以在各自的组件上执行动画。

    playTogether()和playSequentially()函数在开始动画时,只是把每个控件的动画激活,至于每个控件自身的动画是否延时、是否无限循环,只与控件自身的动画设定有关,与playTogether()和playSequentially()函数无关,它们只负责激活动画。
    playSequentially()函数只有在上一个控件做完动画以后,才会激活下一个控件的动画。如果上一个控件的动画是无限循环的,那么下一个控件就别指望能做动画了。

    AnimatorSet可以添加监听,但监听不到repeat事件。

    AnimatorSet的setDuration(long)、setInterpolator(TimeInterpolator)、setTarget(Object)都会覆盖单个ObjectAnimator的设置。
    而setStartDelay()函数不会覆盖单个动画的延时,而且仅针对性地延长AnimatorSet的激活时间,单个动画所设置的setStartDelay()函数仍对单个动画起作用。
    AnimatorSet 真正激活延时= AnimatorSet.startDelay +第一个动画 .startDelay


    4、AnimatorSet.Builder

    AnimatorSet只能实现一起动画和依次动画,但是如果有特定需求(比如:anim1和anim2同时执行,anim3在anim2执行完成后执行,anim4在anim3执行完成后执行),那AnimatorSet就难以做的,这时候就需要AnimatorSet.Builder去构建动画。

    //表示要执行的动画
    public Builder play(Animator anim)
    //自身动画和anim动画一起执行
    public Builder with(Animator anim)
    //先执行完自身动画,再执行anim动画
    public Builder before(Animator anim)
    //anim执行完后,再执行自身动画
    public Builder after(Animator anim)
    //延迟delay毫秒之后执行动画
    public Builder after(long delay)
    

    5、PropertyValuesHolder与Keyframe

    ValueAnimator和ObjectAnimator除了采用ofXXX()静态方法产生实例外,还可以通过ofPropertyValuesHolder()产生实例。

    5.1、PropertyValuesHolder

    PropertyValuesHolder保存了动画过程中所需要操作的属性和对应的值,便于在同一控件上执行组合动画操作(当然AnimatorSet也能实现)。

    private void runPropertyValuesHolder() {
        PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("rotation", 60f, -60f, 40f, 40f, -20f, 20f, 10f, -10f, 0f);
        PropertyValuesHolder alphaHolder = PropertyValuesHolder.ofFloat("alpha", 0.1f, 1f, 0.1f, 1f);
        ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, alphaHolder);
        animator.setDuration(3000);
        animator.start();
    }
    

    5.2、Keyframe

    Keyframe,也就是关键帧,用来表示某一时刻的控件属性的值。一个关键帧必须包含两个元素:时间点和位置。配合PropertyValuesHolder使用,对应关系为:一个ValueAnimator或ObjectAnimator可搭配多个PropertyValuesHolder,一个PropertyValuesHolder可搭配多个Keyframe。

    使用Keyframe的流程:

    1. 生成Keyframe对象
    2. 利用PropertyValuesHolder.ofKeyframe()函数生成PropertyValuesHolder对象
    3. 利用ObjectAnimator.ofPropertyValuesHolder()函数生成对应的Animator。

    四、Interpolator和Evaluator

    Interpolator(插值器):
    Evaluator(估值器):

    image.png

    1、系统自带插值器:

    插值器名称 插值器类 资源ID 解释
    加减速插值器 AccelerateDecelerateInterpolator @android:anim/
    accelerate_decelerate_interpolator
    开始加速,结束减速
    加速插值器 AccelerateInterpolator @android:anim/
    accelerate_interpolator
    开始速率为0,一直加速
    初始偏移插值器 AnticipateInterpolator @android:anim/
    anticipate_interpolator
    先向后运动一段距离,再向前运动
    初始结束偏移插值器 AnticipateOvershootInterpolator @android:anim/
    anticipate_overshoot_interpolator
    初始偏移插值器和结束偏移插值器的合体
    弹跳插值器 BounceInterpolator @android:anim/
    bounce_interpolator
    类似弹球一样
    先加速到终点,再返回一定距离,再去终点,依次这样
    循环插值器 CycleInterpolator @android:anim/
    cycle_interpolator
    会往返运动,最后回到起点
    减速插值器 DecelerateInterpolator @android:anim/
    decelerate_interpolator
    开始速度最大,然后不断减速
    线性插值器 LinearInterpolator @android:anim/
    linear_interpolator
    匀速
    结束偏移插值器 OvershootInterpolator @android:anim/
    overshoot_interpolator
    运动到结束位置,继续向前,再折返

    2、自定义插值器

    自定义插值器,主要通过实现TimeInterpolator接口来完成

    public interface TimeInterpolator {
        /**
         * input参数,取值0~1,表示当前动画运行进度,0表示动画刚开始,1表示动画结束
         * 返回值,表示当前实际要显示的进度,可以超出0~1的范围。小于0表示小于开始位置,大于1表示大于结束位置
         */
        float getInterpolation(float input);
    }
    

    3、自定义估值器

    由于Interpolator主要即使动画实际进度,与具体内容无关,当我们需要计算别的类型值时,比如Point,就需要自定义估值器了!

    自定义估值器,可通过继承TypeEvaluator实现。

    public class PointEvaluator implements TypeEvaluator<PointF> {
        @Override
        public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
            float x = startValue.x + (endValue.x - startValue.x) * fraction;
            float y = startValue.y + (endValue.y - startValue.y) * fraction;
            return new PointF(x, y);
        }
    }
    
    private void runAnimator() {
        ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(), new PointF(0, 0), new PointF(200, 200))
        animator.setDuration(1000);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                PointF point = (PointF) animation.getAnimatedValue();
                Log.d("TAG", "value = " + point);
            }
        });
        animator.setInterpolator(new LinearInterpolator());
        animator.start();
    }
    

    五、ViewPropertyAnimator

    由于构建一个属性动画流程比较繁琐,所以谷歌增加了ViewPropertyAnimator,这些动画依附于控件自身,通过链式调用能够轻松完成动画的创建和执行。
    view.animate().rotation(720).setDuration(1000)
    animate()方法会返回一个ViewPropertyAnimator对象,注意:ViewPropertyAnimator并非派生自Animator,且构建完毕后无需调用start()方法,动画会在界面刷新的时候自动启动。

    由于ViewPropertyAnimator并没有像ObjectAnimator一样使用反射或JNI技术;而ViewPropertyAnimator会根据预设的每一个动画帧计算出对应的所有属性值,并设置给控件,然后调用一次invalidate()函数进行重绘,从而解决了在使用ObjectAnimator时每个属性单独计算、单独重绘的问题。使用ViewPropertyAnimator相对于ObjectAnimator和组合动画,性能有所提升。

    并且要实现一个组合动画,要么采用AnimatorSet实现,要么使用PropertyValuesHolder,比较繁琐,而ViewPropertyAnimator非常方便


    六、为ViewGroup内的组件添加动画

    为ViewGroup内的组件添加动画,常用的有2种方法。

    1、android:animateLayoutChanges属性
    给ViewGroup设置该属性后,当它添加或删除子控件时,都会有默认的动画效果,但注意:该动画不能自定义。

    2、LayoutTransition
    强大且灵活,使用也很方便:
    1、创建实例
    LayoutTransition transition = new LayoutTransition();
    2、创建动画并进行设置
    ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);
    transition.setAnimator(transitionType, animOut);
    3、将LayoutTransition设置到ViewGroup中
    viewGroup.setLayoutTransition(transition);

    transitionType表示容器状态变化类型,目前系统中支持以下5种状态变化:
    1、APPEARING:容器中出现一个视图。
    2、DISAPPEARING:容器中消失一个视图。
    3、CHANGING:布局改变导致某个视图随之改变,例如调整大小,但不包括添加或者移除视图。
    4、CHANGE_APPEARING:其他视图的出现导致某个视图改变。
    5、CHANGE_DISAPPEARING:其他视图的消失导致某个视图改变。

    //初始化
    LayoutTransition layoutTransition = new LayoutTransition();
    
    //统一设置LayoutTransition的动画时间, ANIMATOR_DURATION定义的常量
    layoutTransition.setDuration(LayoutTransition.DISAPPEARING,ANIMATOR_DURATION);
    layoutTransition.setDuration(LayoutTransition.APPEARING, ANIMATOR_DURATION);
    layoutTransition.setDuration(LayoutTransition.CHANGE_DISAPPEARING, ANIMATOR_DURATION);
    layoutTransition.setDuration(LayoutTransition.CHANGE_APPEARING, ANIMATOR_DURATION);
    
    //view 动画改变时,布局中的每个子view动画的时间间隔
    layoutTransition.setStagger(LayoutTransition.CHANGE_APPEARING, 1000);
    layoutTransition.setStagger(LayoutTransition.CHANGE_DISAPPEARING, 1000);
    
    //设置APPEARING行为
    ObjectAnimator appearingAnimator = ObjectAnimator.ofFloat(rootView,"scaleY", 0, 1);
    appearingAnimator.setDuration(layoutTransition.getDuration(LayoutTransition.APPEARING));
    layoutTransition.setAnimator(LayoutTransition.APPEARING,appearingAnimator);
    
    //设置DISAPPEARING行为
    ObjectAnimator disAppearingAnimator = ObjectAnimator.ofFloat(rootView,"scaleY", 1,0);
    disAppearingAnimator.setDuration(layoutTransition.getDuration(LayoutTransition.DISAPPEARING));
    layoutTransition.setAnimator(LayoutTransition.DISAPPEARING,disAppearingAnimator);
    
    PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left", 0, 0);
    PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top", 0, 0);
    PropertyValuesHolder pvhRight = PropertyValuesHolder.ofInt("right", 0, 0);
    PropertyValuesHolder pvhBottom = PropertyValuesHolder.ofInt("bottom", 0, 0);
    
    //设置CHANGE_APPEARING行为
    PropertyValuesHolder animator = PropertyValuesHolder.ofFloat("rotation", 0, 90, 0);
    final ObjectAnimator changeIn = ObjectAnimator.ofPropertyValuesHolder(
    this, pvhTop, pvhBottom,pvhLeft, pvhRight, animator).
    setDuration(layoutTransition.getDuration(LayoutTransition.CHANGE_APPEARING));
    layoutTransition.setAnimator(LayoutTransition.CHANGE_APPEARING, changeIn);
    
    //设置CHANGE_DISAPPEARING
    PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofFloat("scaleX", 1, 1.5f, 1);
    final ObjectAnimator changeOut = ObjectAnimator.ofPropertyValuesHolder(
    this, pvhTop, pvhBottom,pvhLeft, pvhRight, pvhRotation).
    setDuration(layoutTransition.getDuration(LayoutTransition.CHANGE_DISAPPEARING));
    layoutTransition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING, changeOut);
    
    rootView.setLayoutTransition(layoutTransition);
    

    通过代码设置了4中行为动画的duration,然后分别为四种行为设置动画效果。APPEARING和DISAPPEARING比较简单,就是定义了一个ObjectAnimator对象,然后通过setAnimator()方法来设置行为的动画效果。需要特别注意的是CHANGE_APPEARING和CHANGE_DISAPPEARING行为,需要注意的有这几点:
    1、预先定义了left、top、right和bottom四种动画
    2、CHANGE_APPEARING和CHANGE_DISAPPEARING的自定义动画效果必须用PropertyAnimator实现
    3、通过ofPropertyValuesHolder方法实例化ObjectAnimator对象时,必须至少添加left、top、right和bottom中的两种动画,建议全都添加上。如果不想left、top、right和bottom属性发生改变可以在定义的时候使用0,0或者1,1这种参数。
    4、自定义的CHANGE_APPEARING和CHANGE_DISAPPEARING动画效果在构建时需要指定三个参数(如:PropertyValuesHolder.ofFloat("scaleX", 1, 1.5f, 1)),且第三个参数与第一个参数只能保持一致,特别注意的是绝对不能只设置2个参数,会使动画效果无效。这样的理论基础是:View执行CHANGE_APPEARING和CHANGE_DISAPPEARING动画效果之后,不能改变其除因为View添加和移除带来的相对位置改变之外的其他属性值。如上图当Button1被移除时,其他View会有一个scaleX的放大效果,但是当动画结束时其他View不能保持被放大的效果,scaleX必须恢复到原始属性值。


    七、DynamicAnimation

    相关文章

      网友评论

        本文标题:一、Android 动画知识总结(View动画)

        本文链接:https://www.haomeiwen.com/subject/trzblhtx.html