美文网首页
第七单元

第七单元

作者: 贤兵 | 来源:发表于2020-12-13 15:31 被阅读0次
    图片.png

    一、背景

    有了补间动画,为什么还需要属性动画

    补间动画限制:
    1、补间动画只能定义两个关键帧在透明、旋转、位移和倾斜这四个属性的变换,但是属性动画可以定义任何属性的变化。
    3、补间动画只能对 UI 组件(view)执行动画,但属性动画可以对任何对象执行动画。
    4、补间动画没有改变view 的属性,只是加了视觉效果
    5、补间动画效果单一

    属性动画的优势:
    1、任何对象都可以,不在限制于View
    2、不止是四种基本变换

    二、属性动画

    1、常用的类

    图片.png

    ValueAnimator:
    特定时间内执行一个动画,动画执行类,核心
    ObjectAnimator:
    一个对象的一个属性动画,动画执行类
    AnimatorSet:
    动画集合
    TimeAnimator:
    时序监听回调工具
    TimeInterpolator:
    时间差值(插值器接口),控制动画变化率
    TypeEvaluator:
    类型估值(估值器接口),设置属性计算方式,根据属性的始末值和插值一起计算当前时间的属性值
    AnimatorInflate:
    加载属性动画的xml文件
    LayoutTransition:
    布局动画
    ViewPropetyValuesHolder
    为view的动画提供一种更为便捷的用法
    PerpertyValuesHolder
    保存动画过程中所需操作的属性和对应的值
    KeyFrame:
    控制每个时间段执行的动画距离
    AnimationListener:动画事件监听
    AnimationUpdateListener:动画事件监听
    AnimatorListenerAdapter:动画事件监听

    其中:
    插值器:根据时间流逝的百分比计算出当前属性值改变的百分比
    LinearInterpolator(线性插值器):匀速动画。
    AccelerateDecelerateInterpolator(加速减速插值器):动画两头慢,中间快。
    DecelerateInterpolator(减速插值器):动画越来越慢。

    估值器:根据当前属性改变的百分比来计算改变后的属性值。
    IntEvaluator:针对整型属性
    FloatEvaluator:针对浮点型属性
    ArgbEvaluator:针对Color属性

    引用:https://www.cnblogs.com/huolongluo/p/6523552.html

    2、ValueAnimator

    属性动画最核心的类
    控制 值 的变化,之后 手动 赋值给对象的属性,从而实现动画
    ValueAnimator.ofInt(int... values) -- 整型数值
    ValueAnimator.ofFloat(float... values) -- 浮点型数值
    ValueAnimator.ofObject(TypeEvaluator evaluator, Object... values) -- 自定义对象类型

        private void animatorDemo() {
            ValueAnimator valueAnimator = ValueAnimator.ofInt(30, 500);
            valueAnimator.setDuration(3000);
            valueAnimator.setInterpolator(new DecelerateInterpolator());
    //        valueAnimator.setInterpolator(new CycleInterpolator(3));
    //        valueAnimator.setRepeatMode(ValueAnimator.REVERSE);
            valueAnimator.setRepeatMode(ValueAnimator.RESTART);
            valueAnimator.setRepeatCount(2);
    
            valueAnimator.addListener(new Animator.AnimatorListener() {
                @Override
                public void onAnimationStart(Animator animation) {
                    Log.i("Simon", "onAnimationStart");
                }
    
                @Override
                public void onAnimationEnd(Animator animation) {
                    Log.i("Simon", "onAnimationEnd");
                }
    
                @Override
                public void onAnimationCancel(Animator animation) {
                    Log.i("Simon", "onAnimationCancel");
                }
    
                @Override
                public void onAnimationRepeat(Animator animation) {
                    Log.i("Simon", "onAnimationRepeat");
                }
            });
    
            valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    int v = (int)animation.getAnimatedValue();
                    Log.i("Simon", "onAnimationUpdate v: " + v);
    
    //                LinearLayout.LayoutParams param = (LinearLayout.LayoutParams)mImageView.getLayoutParams();
    //                param.leftMargin = v;
    //                mImageView.setLayoutParams(param);
    
                    mImageView.setPadding(v, 0, 0, 0);
                }
            });
    
            valueAnimator.start();
        }
    

    3、ObjectAnimator

    属性 作用 数值类型
    alpha 透明度 float
    translationX X方向的位移 float
    translationY Y方向的位移 float
    scaleX X方向的缩放倍数 float
    scaleY Y方向的缩放倍数 float
    rotation 以屏幕方向为轴的旋转度数 float
    rotationX 以X轴为轴的旋转度数 float
    rotationY 以Y轴为轴的旋转度数 float

    1、xml方式:
    res/animator/alpha.xml

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:propertyName="alpha"
        android:valueFrom="0"
        android:valueTo="1"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:valueType="floatType" />
    

    res/animator/ratation.xml

    <?xml version="1.0" encoding="utf-8"?>
    <objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:repeatCount="1"
        android:repeatMode="reverse"
        android:propertyName="rotation"
        android:valueFrom="100"
        android:valueTo="190"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:valueType="floatType" />
    

    将xml形式的animator读入代码中执行

        private void xmlObjectAnimatorDemo() {
    //        ObjectAnimator objectAnimator = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.alpha);
            ObjectAnimator objectAnimator = (ObjectAnimator)AnimatorInflater.loadAnimator(this, R.animator.roration);
            objectAnimator.setTarget(mImageView);
            objectAnimator.start();
        }
    

    2、纯java代码实现

       private void objectAnimatorDemo() {
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "alpha", 0, 1);
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationX", 0, 200);
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "translationY", 0, 200, 100);
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleX", 1, 5);
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "scaleY", 1, 5);
    //        ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "rotation", 0, 270);
           ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mImageView, "rotationY", 0, 180, -100);
    
           objectAnimator.setDuration(3000);
           objectAnimator.setInterpolator(new AccelerateInterpolator());
    //        objectAnimator.setInterpolator(new DecelerateInterpolator());
    //        objectAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
    //        objectAnimator.setInterpolator(new CycleInterpolator(3));
    //        objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
    //        objectAnimator.setRepeatMode(ValueAnimator.RESTART);
    //        objectAnimator.setRepeatCount(2);
    
           objectAnimator.addListener(new AnimatorListenerAdapter() {
               @Override
               public void onAnimationCancel(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationCancel");
               }
    
               @Override
               public void onAnimationEnd(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationEnd");
               }
    
               @Override
               public void onAnimationRepeat(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationRepeat");
               }
    
               @Override
               public void onAnimationStart(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationStart");
               }
    
               @Override
               public void onAnimationPause(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationPause");
               }
    
               @Override
               public void onAnimationResume(Animator animation) {
                   Log.i("Simon", "AnimatorListenerAdapter onAnimationResume");
               }
           });
           objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
               @Override
               public void onAnimationUpdate(ValueAnimator animation) {
                   Log.i("Simon", "addUpdateListener onAnimationUpdate value:" + animation.getAnimatedValue());
               }
           });
    
           objectAnimator.start();
       }
    

    4、AnimationSet

    AnimatorSet.play(Animator anim) :播放当前动画
    AnimatorSet.after(long delay) :将现有动画延迟x毫秒后执行
    AnimatorSet.with(Animator anim) :将现有动画和传入的动画同时执行
    AnimatorSet.after(Animator anim) :将现有动画插入到传入的动画之后执行
    AnimatorSet.before(Animator anim) : 将现有动画插入到传入的动画之前执行
    AnimatorSet.playSequentially(Animator... items):参数中的动画列表依次执行
    AnimatorSet.playTogether(Animator... items):参数中的动画同时执行

        private void animatorSetDemo() {
            AnimatorSet animatorSet = new AnimatorSet();
            animatorSet.setDuration(3000);
            animatorSet.setInterpolator(new LinearInterpolator());
    
            ObjectAnimator translationX = ObjectAnimator.ofFloat(mImageView, "translationX", 0, 300);
            ObjectAnimator rotation = ObjectAnimator.ofFloat(mImageView, "rotation", 0, 720);
            ObjectAnimator scaleX = ObjectAnimator.ofFloat(mImageView, "scaleX", 1, 5);
            ObjectAnimator scaleY = ObjectAnimator.ofFloat(mImageView, "scaleY", 1, 5);
            ObjectAnimator alpha = ObjectAnimator.ofFloat(mImageView, "alpha", 1, 0);
    
            animatorSet.playSequentially(translationX, rotation, scaleX, scaleY, alpha);
    //        animatorSet.playTogether(scaleX, scaleY);
    
    //        animatorSet.play(translationX).before(rotation);
    //        animatorSet.play(scaleX).with(scaleY).after(3000).before(alpha);
    
            animatorSet.start();
        }
    

    补充: SVG动画

    Google在Android5.X中增加了对SVG矢量图形的支持,这对于创造新的高效率动画具有很深远的意义。

    1、svg

    A.可伸缩矢量图形(Scalable Vector Graphics)
    B.定义用于网络的基于矢量的图形
    C.使用XML格式定义图形
    D.图像在放大或改变尺寸的情况下其图形质量不会有所损失
    E.万维网联盟的标准
    F.与诸如DOM和XML之类的W3C标准是一个整体

    2、path标签

    A. M = moveto(x, y):将画笔移动到指定的坐标位置上,但是并没有发生绘制。
    B. L = lineto(x, y):画一条直线到指定的坐标位置上。
    C. H = horizontal lineto(x):画水平线在指定的x坐标位置。
    D. V = vertical lineto(y):画一条垂直线在指定的y坐标位置。
    E. C = curveto(x1, y1, x2, y2, endX, endY):三次贝赛曲线
    F. S = smooth curveto(x2, y2, endX, endY):三次贝赛曲线
    G. G = quadratic Belzier curveto(x, y, endX, endY):二次贝赛曲线
    H. T = smooth quadratic Belizer curveto(endX, endY):映射前面路径后的终点
    I. A = elliptical Arc(rx, ry, xRotation, flag1, flag2, x, y):弧线
    J. Z = colsepath():关闭路径
    注意:
    A. 坐标轴是以(0,0)为中心的, x轴水平向右,y轴水平向下。
    B. 所有指令大小写均可。大写表示绝对坐标,参照全局坐标系;小写表示相对坐标,参照父容器的坐标系。
    C. 指令和数据间的空格可以省略。
    D. 同一个指令可以使用多次。

    3、例子

    drawable/vector.xml

    <?xml version="1.0" encoding="utf-8"?>
    <vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:width="200dp"
        android:height="200dp"
        android:viewportWidth="110"
        android:viewportHeight="110">
        <group
            android:name="test"
            android:pivotX="55"
            android:pivotY="55">
            <path
                android:pathData="M 26,50
                                  a 25,25,0,0,0,25,25"
                android:strokeWidth="2"
                android:strokeColor="@android:color/holo_blue_bright" />
        </group>
    </vector>
    

    animator/anim.xml

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android">
        <objectAnimator
            android:duration="5000"
            android:interpolator="@android:anim/overshoot_interpolator"
            android:propertyName="rotation"
            android:repeatCount="3"
            android:startOffset="-1"
            android:valueFrom="0"
            android:valueTo="360" />
    </set>
    

    drawable/animated_vector.xml

    <?xml version="1.0" encoding="utf-8"?>
    <animated-vector xmlns:android="http://schemas.android.com/apk/res/android"
        android:drawable="@drawable/vector">
        <target
            android:name="test"
            android:animation="@animator/anim" />
    </animated-vector>
    

    layout/activity_main.xml

    <?xml version="1.0" encoding="utf-8"?>
    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:orientation="vertical"
        tools:context=".MainActivity">
        <ImageView
            android:id="@+id/image_view"
            android:layout_width="300dp"
            android:layout_height="300dp"
            android:src="@drawable/animated_vector" />
        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/button"
            android:text="button" />
    </LinearLayout>
    

    MainActivity.java

    public class MainActivity extends AppCompatActivity {
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            findViewById(R.id.button).setOnClickListener(v -> {
                ImageView imageView = findViewById(R.id.image_view);
                AnimatedVectorDrawable animationDrawable = (AnimatedVectorDrawable)imageView.getDrawable();
                animationDrawable.start();
            });
        }
    }
    
    

    相关文章

      网友评论

          本文标题:第七单元

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