美文网首页自定义view的梳理
android有关动画梳理

android有关动画梳理

作者: ccccccal | 来源:发表于2018-07-19 18:47 被阅读3次

    补间动画

    只能作用在view上,只有四种动画,只是改变view的视觉效果,不会改变view真正的属性
    效果有:平移(Translate),缩放(scale),旋转(rotate),透明度(alpha)

    补间动画使用方式,在anim创建xml文件,使用代码动态开启动画

    平移动画 translate

    使用xml

    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
    
        android:duration="3000" // 动画持续时间(ms),必须设置,动画才有效果
        android:startOffset ="1000" // 动画延迟开始时间(ms)
        android:fillBefore = “true” // 动画播放完后,视图是否会停留在动画开始的状态,默认为true
        android:fillAfter = “false” // 动画播放完后,视图是否会停留在动画结束的状态,优先于fillBefore值,默认为false
        android:fillEnabled= “true” // 是否应用fillBefore值,对fillAfter值无影响,默认为true
        android:repeatMode= “restart” // 选择重复播放动画模式,restart代表正序重放,reverse代表倒序回放,默认为restart|
        android:repeatCount = “0” // 重放次数(所以动画的播放次数=重放次数+1),为infinite时无限重复
        android:interpolator = @[package:]anim/interpolator_resource // 插值器,即影响动画的播放速度,下面会详细讲
        
        android:fromXDelta="0" // 视图在水平方向x 移动的起始值
        android:toXDelta="500" // 视图在水平方向x 移动的结束值
        android:fromYDelta="0" // 视图在竖直方向y 移动的起始值
        android:toYDelta="500" // 视图在竖直方向y 移动的结束值 />
    

    java代码

            Animation animation = AnimationUtils.loadAnimation(this, R.anim.translateanim);
            button.startAnimation(animation);
    
            TranslateAnimation translateAnimation = new TranslateAnimation(0, 500, 0, 500);
            translateAnimation.setDuration(2000);
            button.startAnimation(translateAnimation);
    

    缩放动画 scale

    使用xml

    <?xml version="1.0" encoding="utf-8"?>
    <scale  xmlns:android="http://schemas.android.com/apk/res/android"
    
        android:fromXScale="0.0" 
        // 动画在水平方向X的起始缩放倍数
        // 0.0表示收缩到没有;1.0表示正常无伸缩
        // 值小于1.0表示收缩;值大于1.0表示放大
    
        android:toXScale="2"  //动画在水平方向X的结束缩放倍数
    
        android:fromYScale="0.0" //动画开始前在竖直方向Y的起始缩放倍数
        android:toYScale="2" //动画在竖直方向Y的结束缩放倍数
    
        android:pivotX="50%" // 缩放轴点的x坐标
        android:pivotY="50%" // 缩放轴点的y坐标
        // 轴点 = 视图缩放的中心点
    
        // pivotX pivotY,可取值为数字,百分比,或者百分比p
        // 设置为数字时(如50),轴点为View的左上角的原点在x方向和y方向加上50px的点。在Java代码里面设置这个参数的对应参数是Animation.ABSOLUTE。
        // 设置为百分比时(如50%),轴点为View的左上角的原点在x方向加上自身宽度50%和y方向自身高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_SELF。
        // 设置为百分比p时(如50%p),轴点为View的左上角的原点在x方向加上父控件宽度50%和y方向父控件高度50%的点。在Java代码里面设置这个参数的对应参数是Animation.RELATIVE_TO_PARENT />
    

    java 代码

            Button mButton = (Button) findViewById(R.id.Button);
            // 步骤1:创建 需要设置动画的 视图View
            Animation rotateAnimation = AnimationUtils.loadAnimation(this, R.anim.view_animation);
            // 步骤2:创建 动画对象 并传入设置的动画效果xml文件
            mButton.startAnimation(scaleAnimation);
    
    
    
            Button mButton = (Button) findViewById(R.id.Button);
            Animation rotateAnimation = new ScaleAnimation(0,2,0,2,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
            // 步骤2:创建缩放动画的对象 & 设置动画效果:缩放动画对应的Animation子类为RotateAnimation
            // 参数说明:
            // 1. fromX :动画在水平方向X的结束缩放倍数
            // 2. toX :动画在水平方向X的结束缩放倍数
            // 3. fromY :动画开始前在竖直方向Y的起始缩放倍数
            // 4. toY:动画在竖直方向Y的结束缩放倍数
            // 5. pivotXType:缩放轴点的x坐标的模式
            // 6. pivotXValue:缩放轴点x坐标的相对值
            // 7. pivotYType:缩放轴点的y坐标的模式
            // 8. pivotYValue:缩放轴点y坐标的相对值
    
            // pivotXType = Animation.ABSOLUTE:缩放轴点的x坐标 =  View左上角的原点 在x方向 加上 pivotXValue数值的点(y方向同理)
            // pivotXType = Animation.RELATIVE_TO_SELF:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 自身宽度乘上pivotXValue数值的值(y方向同理)
            // pivotXType = Animation.RELATIVE_TO_PARENT:缩放轴点的x坐标 = View左上角的原点 在x方向 加上 父控件宽度乘上pivotXValue数值的值 (y方向同理)
    
            scaleAnimation.setDuration(3000);
            mButton.startAnimation(scaleAnimation);
    

    旋转动画 rotate

    使用xml

          <?xml version="1.0" encoding="utf-8"?>
          <rotate xmlns:android="http://schemas.android.com/apk/res/android"
    
            android:duration="1000"
            android:fromDegrees="0" // 动画开始时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
            android:toDegrees="270" // 动画结束时 视图的旋转角度(正数 = 顺时针,负数 = 逆时针)
            android:pivotX="50%" // 旋转轴点的x坐标
            android:pivotY="0" // 旋转轴点的y坐标 />
    

    java 代码

            Animation rotateAnimation = new RotateAnimation(0, 270, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
            rotateAnimation.setDuration(2000);
            button.startAnimation(rotateAnimation);
    
    

    透明度

    使用 xml

          <?xml version="1.0" encoding="utf-8"?>
          <alpha xmlns:android="http://schemas.android.com/apk/res/android"
             // 以下参数是透明度动画特有的属性
            android:fromAlpha="1.0" // 动画开始时视图的透明度(取值范围: -1 ~ 1)
            android:toAlpha="0.0"// 动画结束时视图的透明度(取值范围: -1 ~ 1)/>
    

    java 代码

            Button mButton = (Button) findViewById(R.id.Button);
            // 步骤1:创建 需要设置动画的 视图View
    
            Animation alphaAnimation = new AlphaAnimation(1,0);
            // 步骤2:创建透明度动画的对象 & 设置动画效果:透明度动画对应的Animation子类为AlphaAnimation
            // 参数说明:
            // 1. fromAlpha:动画开始时视图的透明度(取值范围: -1 ~ 1)
            // 2. toAlpha:动画结束时视图的透明度(取值范围: -1 ~ 1)
    
            alphaAnimation.setDuration(3000);
            // 固定属性的设置都是在其属性前加“set”,如setDuration()
    
            mButton.startAnimation(alphaAnimation);
    

    组合动画

    使用 xml

    <?xml version="1.0" encoding="utf-8"?>
    // 采用< Set/>标签
    <set xmlns:android="http://schemas.android.com/apk/res/android">
    
    // 组合动画独特的属性
        android:shareinterpolator = “true”
        // 表示组合动画中的动画是否和集合共享同一个差值器
        // 如果集合不指定插值器,那么子动画需要单独设置
    
    // 组合动画播放时是全部动画同时开始
    // 如果想不同动画不同时间开始就要使用android:startOffset属性来延迟单个动画播放时间
    
    
        <rotate
            android:duration="1000"
            android:fromDegrees="0"
            android:toDegrees="360"
            android:pivotX="50%"
            android:pivotY="50%"
            android:repeatMode="restart"
            android:repeatCount="infinite"/>
    
        <translate
            android:duration="10000"
            android:startOffset = “1000”
            android:fromXDelta="-50%p"
            android:fromYDelta="0"
            android:toXDelta="50%p"
            android:toYDelta="0" />
    
        <alpha
            android:startOffset="7000"
            android:duration="3000"
            android:fromAlpha="1.0"
            android:toAlpha="0.0" />
    
        <scale
            android:startOffset="4000"
            android:duration="1000"
            android:fromXScale="1.0"
            android:fromYScale="1.0"
            android:pivotX="50%"
            android:pivotY="50%"
            android:toXScale="0.5"
            android:toYScale="0.5"/>
    
        1. 在组合动画里scale缩放动画设置的repeatCount(重复播放)和fillBefore(播放完后,视图是否会停留在动画开始的状态)是无效的。
        2. 所以如果需要重复播放或者回到原位的话需要在set标签里设置
        3. 但是由于此处rotate旋转动画里已设置repeatCount为infinite,所以动画不会结束,也就看不到重播和回复原位
    </set>
    

    使用 java代码

            Button mButton = (Button) findViewById(R.id.Button);
            // 创建 需要设置动画的 视图View
    
            // 组合动画设置
            AnimationSet setAnimation = new AnimationSet(true);
            // 步骤1:创建组合动画对象(设置为true)
    
    
            // 步骤2:设置组合动画的属性
            // 特别说明以下情况
            // 因为在下面的旋转动画设置了无限循环(RepeatCount = INFINITE)
            // 所以动画不会结束,而是无限循环
            // 所以组合动画的下面两行设置是无效的
            setAnimation.setRepeatMode(Animation.RESTART);
            setAnimation.setRepeatCount(1);// 设置了循环一次,但无效
    
            // 子动画1:旋转动画
            Animation rotate = new RotateAnimation(0,360,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
            rotate.setDuration(1000);
            rotate.setRepeatMode(Animation.RESTART);
            rotate.setRepeatCount(Animation.INFINITE);
    
            // 子动画2:平移动画
            Animation translate = new TranslateAnimation(TranslateAnimation.RELATIVE_TO_PARENT,-0.5f,
                    TranslateAnimation.RELATIVE_TO_PARENT,0.5f,
                    TranslateAnimation.RELATIVE_TO_SELF,0
                    ,TranslateAnimation.RELATIVE_TO_SELF,0);
            translate.setDuration(10000);
    
            // 子动画3:透明度动画
            Animation alpha = new AlphaAnimation(1,0);
            alpha.setDuration(3000);
            alpha.setStartOffset(7000);
    
            // 子动画4:缩放动画
            Animation scale1 = new ScaleAnimation(1,0.5f,1,0.5f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
            scale1.setDuration(1000);
            scale1.setStartOffset(4000);
    
            // 步骤4:将创建的子动画添加到组合动画里
            setAnimation.addAnimation(alpha);
            setAnimation.addAnimation(rotate);
            setAnimation.addAnimation(translate);
            setAnimation.addAnimation(scale1);
    
            mButton.startAnimation(setAnimation);
    

    帧动画,将动画切割为多张图片

    使用xml创建

      <?xml version="1.0" encoding="utf-8"?>
      <animation-list
        xmlns:android="http://schemas.android.com/apk/res/android"
        android:oneshot="true" 
        // 设置是否只播放一次,默认为false>
    
        //item = 动画图片资源;duration = 设置一帧持续时间(ms)
        <item android:drawable="@drawable/a0" android:duration="100"/>
        <item android:drawable="@drawable/a1" android:duration="100"/>
        <item android:drawable="@drawable/a2" android:duration="100"/>
        <item android:drawable="@drawable/a3" android:duration="100"/>
        <item android:drawable="@drawable/a4" android:duration="100"/>
        <item android:drawable="@drawable/a5" android:duration="100"/>
        <item android:drawable="@drawable/a6" android:duration="100"/>
        <item android:drawable="@drawable/a7" android:duration="100"/>
    </animation-list>
    

    使用java代码

            ImageView imageView = new ImageView(this);
            imageView.setImageResource(R.drawable.ic_launcher_background);
            AnimationDrawable animationDrawable = (AnimationDrawable) imageView.getDrawable();
            animationDrawable.start();
            animationDrawable.stop();
            
            
            //动态创建帧动画
            AnimationDrawable animationDrawable1 = new AnimationDrawable();
            for (int i = 0; i < 10; i++) {
                int drawable = getResources().getIdentifier("aaa" + i, "drawable", getPackageName());
                Drawable drawable1 = getResources().getDrawable(drawable);
                animationDrawable1.addFrame(drawable1,100);
            }
            animationDrawable1.setOneShot(true);
            ImageView imageView1 = new ImageView(this);
            imageView.setImageResource(R.drawable.ic_launcher_background);
            //开启动画之前先停止动画,不然第一次动画之后会停留在最后一帧,这样动画就只会触发一次
            animationDrawable1.stop();
            animationDrawable1.start();
            
    

    监听动画过程

        alphaAnimation.setAnimationListener(new Animation.AnimationListener() {
                @Override
                public void onAnimationStart(Animation animation) {
                    
                }
    
                @Override
                public void onAnimationEnd(Animation animation) {
    
                }
    
                @Override
                public void onAnimationRepeat(Animation animation) {
    
                }
            });
    

    属性动画可以采用以下监听

     ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 120f);
            valueAnimator.addListener(new AnimatorListenerAdapter() {
                @Override
                public void onAnimationStart(Animator animation) {
                    super.onAnimationStart(animation);
                }
            });
    

    属性动画

    3.0之后出现。顾名思义,为了改变view的某一个属性的动画

    使用步骤如下:

    1. 设置动画运行时长,动画效果以及对应属性的初始值和结束值
    2. 设置从开始到结束的变化逻辑
    • 设置值变化的模式趋势使用插值器,自定义插值器需要实现interpolator接口
    • 设置值变化的具体数值使用估值器,自定义估值器实现TypeEvaluator接口
    1. 根据变化不断改变值得效果
    2. 值每改变一次,就赋值给view的属性一次,
    • 手动赋值使用-valueAnimator
    • 自动赋值使用-ObjectAnimator
    1. 每次调用invalidate();不断刷新视图直到初始值变为结束值

    ValueAnimator 手动赋值给对象的属性,实现动画效果

    自带估值器有:

    • ValueAnimator ofInt(int... values),整型估值器
    • ValueAnimator ofFloat(float... values) ,浮点型估值器
    • ValueAnimator ofObject(TypeEvaluator evaluator, Object... values)操作对象实现动画效果

    整型或者浮点型估值器

            //设置动画属性的初始值以及结束值,ofInt创建动画实例,讲传入的多个Int型参数进行平滑过渡,内置整型估值器,直接使用默认
            final ValueAnimator valueAnimator = ValueAnimator.ofInt(100, 180, 500, 700, 600);
    
            mButton = findViewById(R.id.button2);
    
            valueAnimator.setDuration(2000);//播放时间
            valueAnimator.setStartDelay(100);//延迟播放时间
            valueAnimator.setRepeatCount(0);//设置播放次数,-1就是无限循环
            valueAnimator.setRepeatMode(ValueAnimator.REVERSE);//设置重复播放模式ValueAnimator.RESTART(默认):正序重放,ValueAnimator.REVERSE:倒序回放
    
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int animatedValue = (Integer) valueAnimator.getAnimatedValue();
    
                    mButton.setText("---" + animatedValue);
    
                    mButton.setTranslationX(animatedValue);
                    mButton.getLayoutParams().width = animatedValue;
                    mButton.getLayoutParams().height = animatedValue;
                    mButton.setRotation(animatedValue);
                    mButton.setAlpha(animatedValue);
    
                    mButton.requestLayout();//刷新view的位置
                }
            });
            valueAnimator.start();
    

    ValueAnimator.ofObject()将初始值 以对象的形式 过渡到结束值

    public class ObjectEvaluatorView extends View {
    
        private Paint mPaint;
        private Point mPoint;
    
        private static final int ROUND = 81;
    
        public ObjectEvaluatorView(Context context) {
            this(context, null);
        }
    
        public ObjectEvaluatorView(Context context, @Nullable AttributeSet attrs) {
    
            this(context, attrs, 0);
        }
    
        public ObjectEvaluatorView(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
            super(context, attrs, defStyleAttr);
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(Color.YELLOW);
            mPaint.setTextSize(120);
        }
    
        @Override
        protected void onDraw(Canvas canvas) {
            super.onDraw(canvas);
            if (mPoint == null) {
                mPoint = new Point(ROUND,ROUND);
    
                canvas.drawCircle(ROUND,ROUND,ROUND,mPaint);
    
                Point point = new Point(600, 800);
                Point point3 = new Point(80, 1200);
                Point point4 = new Point(80, 80);
    
                ValueAnimator valueAnimator = ValueAnimator.ofObject(new ObjectEvaluator(), mPoint, point,point3,point4);
                valueAnimator.setDuration(3000);
                valueAnimator.setRepeatCount(-1);
    
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        mPoint = (Point) animation.getAnimatedValue();
    
                        invalidate();
                    }
                });
    
                valueAnimator.start();
    
            }else {
                canvas.drawText("😄",mPoint.getX(),mPoint.getY(),mPaint);
            }
        }
    }
    

    ObjectAnimator自动赋值实现动画效果,直接操作对象的属性

    基本的四种属性:

            ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton3, "alpha", 1f, 0f, 100f);
            alpha.setDuration(3000);
            alpha.setRepeatCount(-1);
            alpha.start();
    
            ObjectAnimator rotation = ObjectAnimator.ofFloat(mButton3, "rotation", 1f, 360f, 100f);
            rotation.setDuration(3000);
            rotation.setRepeatCount(-1);
            rotation.start();
    
            ObjectAnimator translationX = ObjectAnimator.ofFloat(mButton3, "translationY", 1f, 360f, 100f);
            translationX.setDuration(3000);
            translationX.setRepeatCount(-1);
            translationX.start();
    
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(mButton3, "scaleY", 1f, 4f, 1f);
            scaleY.setDuration(3000);
            scaleY.setRepeatCount(-1);
            scaleY.start();
    
    属性 作用
    Alpha 控制view的透明度
    TranslationX 控制x轴方向位移
    TranslationY K通知y轴方向位移
    ScaleX 控制x轴方向缩放倍数
    ScaleY 控制y轴方向缩放倍数
    Rotation 控制以屏幕方向为轴的旋转度数
    RotationX 控制以x轴为轴的旋转度数
    RotationY 控制以y轴为轴的旋转度数

    扩展自定义属性

    两种方式:

    1. 通过集成原始类,添加get()和set()方法
    public class MyView2 extends View {
        // 设置需要用到的变量
        public static final float RADIUS = 100f;// 圆的半径 = 100
        private Paint mPaint;// 绘图画笔
    
        private String color;
        // 设置背景颜色属性
    
        // 设置背景颜色的get() & set()方法
        public String getColor() {
            return color;
        }
    
        public void setColor(String color) {
            this.color = color;
            mPaint.setColor(Color.parseColor(color));
            // 将画笔的颜色设置成方法参数传入的颜色
            invalidate();
            // 调用了invalidate()方法,即画笔颜色每次改变都会刷新视图,然后调用onDraw()方法重新绘制圆
            // 而因为每次调用onDraw()方法时画笔的颜色都会改变,所以圆的颜色也会改变
        }
    
    
        // 构造方法(初始化画笔)
        public MyView2(Context context, AttributeSet attrs) {
            super(context, attrs);
            // 初始化画笔
            mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
            mPaint.setColor(Color.BLUE);
        }
    
        // 复写onDraw()从而实现绘制逻辑
        // 绘制逻辑:先在初始点画圆,通过监听当前坐标值(currentPoint)的变化,每次变化都调用onDraw()重新绘制圆,从而实现圆的平移动画效果
        @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawCircle(500, 500, RADIUS, mPaint);
        }
    }
    
    1. 添加包装类,传递对象进入,封装get()和set()方法
    
            ObjectAnimator alpha = ObjectAnimator.ofObject(new Test(mButton3), "text", new Bbb(), "asdasd", "qweqweqweqw", "zxczxczxczc");
            alpha.setDuration(3000);
            alpha.setRepeatCount(-1);
            alpha.start();
    
    
        //自定义包装类
         private class Test{
            private Button mView;
    
            public Test(Button view) {
                mView = view;
            }
            public String getText(){
                return mView.getText().toString();
            }
            public void setText(String s){
                mView.setText(s);
            }
        }
    
    
        //自定义估值器
        private class Bbb implements TypeEvaluator {
    
            @Override
            public Object evaluate(float fraction, Object startValue, Object endValue) {
                return startValue;
            }
        }
    
    

    组合动画

    AnimatorSet.play(Animator anim)   :播放动画
    AnimatorSet.after(long delay)   :动画延迟x毫秒后执行
    AnimatorSet.with(Animator anim)   :现有动画和传入的动画同时执行
    AnimatorSet.after(Animator anim)   :现有动画插入到传入的动画之后执行
    AnimatorSet.before(Animator anim) :  现有动画插入到传入的动画之前执行
    
    

    使用方式如下:

    // 步骤1:设置需要组合的动画效果
    ObjectAnimator translation = ObjectAnimator.ofFloat(mButton, "translationX", curTranslationX, 300,curTranslationX);  
    
    ObjectAnimator rotate = ObjectAnimator.ofFloat(mButton, "rotation", 0f, 360f);  
    
    ObjectAnimator alpha = ObjectAnimator.ofFloat(mButton, "alpha", 1f, 0f, 1f);  
    
    AnimatorSet animSet = new AnimatorSet();  
    
    animSet.play(translation).with(rotate).before(alpha);  
    animSet.setDuration(5000);  
    animSet.start();
    

    属性动画简写方式:

            mButton = (Button) findViewById(R.id.Button);
            mButton.animate().alpha(0f);
            mButton.animate().alpha(0f).setDuration(5000).setInterpolator(new BounceInterpolator());
            mButton.animate().alpha(0f).x(500).y(500);
    

    插值器和估值器

    • 设置值变化的模式趋势使用插值器,自定义插值器需要实现interpolator接口
    • 设置值变化的具体数值使用估值器,自定义估值器实现TypeEvaluator接口

    系统默认自带插值器有:

    java类 作用
    AccelerateInterpolator 加速,开始时慢中间加速,系统默认
    DecelerateInterpolator 减速,开始时快然后减速
    AccelerateDecelerateInterolator 先加速后减速,开始结束时慢,中间加速
    AnticipateInterpolator 反向,先向相反方向改变一段再加速播放
    AnticipateOvershootInterpolator 反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值
    BounceInterpolator 跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100
    CycleIinterpolator 循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input)
    LinearInterpolator 线性,线性均匀改变
    OvershootInterpolator 超越,最后超出目的值然后缓慢改变到目的值

    自定义插值器

    补间动画 实现 Interpolator接口;属性动画实现TimeInterpolator接口

         private class Ccc implements TimeInterpolator {
            /**
             * @param input 范围变化1-0,
             * @return
             */
            @Override
            public float getInterpolation(float input) {
                float aa;
                if (input <= 0.5) {
                    aa = (float) ((Math.sin(Math.PI * input)) / 2);
                } else {
                    aa = (float) (2 - Math.sin(Math.PI * input) / 2);
                }
                return aa;
            }
        }
    

    自定义估值器

        private class Bbb implements TypeEvaluator {
    
            @Override
            public Object evaluate(float fraction, Object startValue, Object endValue) {
    
                return startValue;
            }
        }
    

    相关文章

      网友评论

      本文标题:android有关动画梳理

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