第七单元

图片.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();
        });
    }
}

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,224评论 6 529
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 97,916评论 3 413
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,014评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,466评论 1 308
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,245评论 6 405
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,795评论 1 320
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,869评论 3 440
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,010评论 0 285
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,524评论 1 331
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,487评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,634评论 1 366
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,173评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,884评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,282评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,541评论 1 281
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,236评论 3 388
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,623评论 2 370

推荐阅读更多精彩内容