高级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();
    }
相关文章
相关标签/搜索