高级UI - Android动画基本使用

一、传统的2D动画—补间动画+帧动画

实现的本质是什么?canvas绘制的---矩阵变换Matrix

补间动画是一种设定动画开始状态、结束状态,其中间的变化由系统计算补充。这也是他叫做补间动画的原因。

补间动画由Animation类来实现具体效果,包括平移(TranslateAnimation)、缩放(ScaleAnimation)、旋转(RotateAnimation)、透明度(AlphaAnimation)四个子类,四种变化。

二、属性动画

属性动画基础

API 3.0以后。
1.属性动画的系统使用;

2.案例

3.源码解析

4.结合前面一些特效+属性动画—综合案例

1.什么是属性动画?属性动画有什么特点?

比如

button.setTranslationX(200);

和传统补间动画的区别:—会改变view的实际属性。比如:改变button的位置,平移后的状态还是可以被点击的

2.属性动画

3.0_API以下的兼容方案:NineOldAndroid.jar

主要几个类

1.ObjectAnimator

2.ValueAnimator 

3.PropertyValueHolder

4. TypeEvaluator 估值器---改变算法--改变值

5. Interpolator 插值器---控制计算的速度

Facebook Rebound 弹性动画库

属性动画效率高 还是补间动画效率高-- 补间动画

动画基本使用

动画1. 直接操作属性

mark

对应代码



    private void startAnimation1() {
        //补间动画
        //Animation loadAnimation = AnimationUtils.loadAnimation(this,R.anim)

        //属性动画 的属性
        ivTest.setTranslationX(120);//平移
        ivTest.setScaleX(1.3f);//缩放
        ivTest.setAlpha(0.5f);//透明度
        ivTest.setRotation(20);//旋转
//        ivTest.setBackgroundColor(color);//颜色渐变
    }

动画2. OjbectAnimator基本使用

使用ObjectAnimator 平移

mark

对应代码

    //属性动画基本使用
    private void startAnimation2() {

        //参数 1  那个控件  参数2 属性的那种动画 (通过反射的方式)  参数3 数值 不断赋值 从0 到200
        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "translationX", 0f, 200f);//平移
//        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest,"backgroundColor", red,green);//颜色
        objectAnimator.setDuration(500);
        objectAnimator.start();
    }

多个动画同时执行

动画3 方法1: 设置动画监听 同步操作其他属性

mark


    //多个动画同时执行
    private void startAnimation3() {


        //方法1;----------------------- 设置动画监听 同步操作其他属性-------------

        //参数 1  那个控件  参数2 属性的那种动画 (通过反射的方式)  参数3 数值 不断赋值 从0 到200
//        @SuppressLint("ObjectAnimatorBinding") ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "test", 0f, 200f);//平移
        @SuppressLint("ObjectAnimatorBinding") ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(ivTest, "setTranslationX", 0f, 100f);//平移
        //实际这个操作 是 ivTest 身上的属性 叫做test; 如果参数 1 是this 则是当前java类的方法
        //TODO 第二个参数是正在动画化的属性的名称 如果随便写 也可以 需要在AnimatorUpdateListener 中完成相应的动画
        objectAnimator.setDuration(500);//持续时间
        //添加监听 同步操作其他属性
        objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //监听动画回调
//                animation.getAnimatedFraction(); //得到动画执行的百分比 0 - 1;
//                animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
                float value = (float) animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
                Log.d(TAG, "onAnimationUpdate: value = " + value);
//                ivTest.setScaleX(value/100);
//                ivTest.setScaleY(value/100);
                ivTest.setScaleX(0.5f + value / 200);
                ivTest.setScaleY(0.5f + value / 200);
//                ivTest.setTranslationX(value);
            }
        });
        objectAnimator.start();

        objectAnimator.setRepeatCount(2);//设置重复次数
//        objectAnimator.setRepeatCount(ValueAnimator.INFINITE);//无限

//        objectAnimator.setRepeatMode(ValueAnimator.RESTART);//重新开始
//        objectAnimator.setRepeatMode(ValueAnimator.REVERSE);//翻转


        // 设置其他监听

        objectAnimator.addListener(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) {

            }
        });


    }
动画4 ,方法2 使用valueAnimator 只需要监听值的变化

同样的动画

mark

public void startAnimator4() {
        //添加监听  适配器模式
//        objectAnimator.addListener(new AnimatorListenerAdapter() {
//        });


        //方法2;----------------------- 使用 ValueAnimator -----只需要监听值的变化-------
        ValueAnimator animator = ValueAnimator.ofFloat(0f, 100f);
        animator.setDuration(200);
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();//得到0f-100f当中的这个时间点对应的值
                Log.d(TAG, "onAnimationUpdate: value = " + value);
//                ivTest.setScaleX(value/100);
//                ivTest.setScaleY(value/100);
                ivTest.setScaleX(0.5f + value / 200);
                ivTest.setScaleY(0.5f + value / 200);
            }
        });
        animator.start();
    }
动画5 方法3 PropertyValuesHolder

mark

对应代码

    public void startAnimator5() {
        //方法3 PropertyValuesHolder
        PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("alpha", 1f, 0.5f);
        PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleX", 1f, 0.5f);
        PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("scaleY", 1f, 0.5f);

        ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(ivTest, holder1, holder2, holder3);
        objectAnimator.setDuration(200);
        objectAnimator.start();
    }

动画6 动画集合AnimatorSet

mark

对应代码

    public void startAnimator6() {
        //动画集合  AnimatorSet
        ObjectAnimator objectAnimator1 = ObjectAnimator.ofFloat(ivTest, "translationX", 0f, 100f);//平移
        ObjectAnimator objectAnimator2 = ObjectAnimator.ofFloat(ivTest, "scaleX", 1f, 2f);//平移
        ObjectAnimator objectAnimator3 = ObjectAnimator.ofFloat(ivTest, "scaleY", 1f, 2f);//平移

        AnimatorSet animatorSet = new AnimatorSet();
        animatorSet.setDuration(200);
//        animatorSet.playTogether(objectAnimator1);
        animatorSet.playTogether(objectAnimator1, objectAnimator2, objectAnimator3);
//        animatorSet.playSequentially(objectAnimator1,objectAnimator2,objectAnimator3);//按照顺序执行
        animatorSet.start();

        // objectAnimator1和 objectAnimator2同时开启动画, objectAnimator2 在 objectAnimator3 的后面
//        animatorSet.play(objectAnimator1).with(objectAnimator2).after(objectAnimator3);
    }

动画7 实现抛物线动画 估值器的使用

mark

对应代码

  /**
     * 实现一个抛物线的效果--购物车动画.股指数--  重力加速度
     */
    public void startAnimator7() {
        //思路
        /**
         * X:匀速
         * y: 加速度 y = vt = 1/2*g*t*t
         * 使用估值器  setEvaluator
         *
         */
        ValueAnimator valueAnimator = new ValueAnimator();
//          valueAnimator.setInterpolator(); //设置
//          valueAnimator.setEvaluator();
        valueAnimator.setDuration(1000);
        //这里约束 animator 的约束 是pointf
        valueAnimator.setObjectValues(new PointF(0, 0));
        //这是从 00 到100,100 按照3000 的时间自己进行估值计算
//            valueAnimator.setObjectValues(new PointF(0,0),new PointF(100,100));

        //对这个点进行操作
        final PointF pointF = new PointF();
//        valueAnimator.setEvaluator(new ArgbEvaluator());//颜色估值器
        valueAnimator.setEvaluator(new TypeEvaluator<PointF>() {
            /**
             *
             * @param fraction 执行的百分比
             * @param startValue
             * @param endValue
             * @return
             */
            @Override
            public PointF evaluate(float fraction, PointF startValue, PointF endValue) {
                //evaluate 估值计算方法--可以在执行的过程当中干预改变属性的值---做效果:用自己的算法来控制
                //不断的计算修改坐标
                //X 坐标匀速运动 x = vt; 为了看起来效果好让t变成fraction*5
                pointF.x = 100f * (fraction * 5);
                //y 坐标是根据重力加速度公式来计算  加速度 y = vt = 1/2*g*t*t;
//                pointF.y = 0.5f * 9.8f * (fraction * 5) * (fraction * 5);
                pointF.y = 10f * 0.5f * 9.8f * (fraction * 5) * (fraction * 5);//Y 做大一点
                return pointF;
            }


        });

        //设置监听
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //为什么可以从 animation 里面 取到pointf  因为 setObjectValues 约束 和在估值器中 也设置了约束<PointF>

                PointF f = (PointF) animation.getAnimatedValue();
                ivTest.setX(f.x);
                ivTest.setY(f.y);
            }
        });

        valueAnimator.start();
    }

动画8 插值器的使用

mark

对应代码

    /**
     * 插值器 加速器 使用 setInterpolator
     */
    public void startAnimator8() {
        ObjectAnimator animator = ObjectAnimator.ofFloat(ivTest, "translationY", 0f, 1000f);
        animator.setDuration(500);

//        Interpolator interpolator = new Interpolator()
//        animator.setInterpolator(new AccelerateInterpolator(1));//加速度
//        animator.setInterpolator(new AccelerateDecelerateInterpolator());//先快后慢
        animator.setInterpolator(new BounceInterpolator());//一个内插器,它的变化在末端反弹。
//        animator.setInterpolator(new AnticipateInterpolator());//一个内插器,在那里,变化开始向后,然后向前移动。
//        animator.setInterpolator(new CycleInterpolator(5));//往返运动

        animator.start();
    }


AccelerateDecelerateInterpolator   在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
AccelerateInterpolator                     在动画开始的地方速率改变比较慢,然后开始加速
AnticipateInterpolator                      开始的时候向后然后向前甩
AnticipateOvershootInterpolator     开始的时候向后然后向前甩一定值后返回最后的值
BounceInterpolator                          动画结束的时候弹起
CycleInterpolator                             动画循环播放特定的次数,速率改变沿着正弦曲线
DecelerateInterpolator                    在动画开始的地方快然后慢
LinearInterpolator                            以常量速率改变
OvershootInterpolator                      向前甩一定值后再回到原来位置
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值