#Android 动画之属性动画(四)#

Android 动画之属性动画(四)#


Specifying Keyframes##

有些时候,我们需要这个动画在进程的某一个时刻,达到某一个指定的值。比如说你实现一个位移动画,然后你想在进程的1/2,位移走到3/4,当然你可以重写 TimeInterpolator 达到这样的效果,但是如果情况更加复杂,那么难以保证你可以写出正确的逻辑来满足要求,于是就有了 Keyframes

Keyframe ,就是关键帧,也就是 flash 里面的关键帧。flash 里面的关键帧就是,在指定位置,你放一张帧,然后系统就会自动为两个关键帧计算出补间动画。紧连着的两个帧之间,之间的动画的 Interpolator 也是可以分别指定的

Keyframe 的使用方法:

  1. 首先获得一个Keyframe对象,对象的获得一般是通过调用 ofInt(), ofFloat(), or ofObject() 来获得。ofFloat( float fraction, float value ) 具体来看参数,第一个参数为 fraction ,也就是之前讲到的代表进程的参数,第二个就是 value 就是 Interpolator 返回的值。这个方法意思就是这一帧在进程为 fraction 的时候,对应的值为 value
  2. 利用 PropertyValuesHolder.ofKeyframe( String propertyName, Keyframe... values ) ,把 Keyframe封装到 PropertyValuesHolder 里面
  3. 调用 ObjectAnimator.ofPropertyValuesHolder( Object target, PropertyValuesHolder... pvhRotation ) 方法为 ObjectAnimator 设置动画

具体代码:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation)
rotationAnim.setDuration(5000ms);
//这样,可以把动画看做看做有三个关键帧,分别是在进程为0的时候value为0,在进程为1/2的时候值为360...

大家可以看到,ObjectAnimator.ofPropertyValuesHolder( Object target, PropertyValuesHolder... pvhRotation ) 的第二个参数是不定的,也就是说,我们可以传入若干个 PropertyValuesHolder ,也就是说我们可以实现两个动画效果同时发生。按照以前所讲的,要两个动画同时进行的方法是:

    ObjectAnimator ob1 = ObjectAnimator.ofFloat(myView,"rotation",0f,125f,0,-125f,0f);
    ObjectAnimator ob2 = ObjectAnimator.ofFloat(myView,"textSize",25f,50f,25f,50f,25f);
    AnimatorSet animatorSet = new AnimatorSet();
    animatorSet.play(ob1).with(ob2);
    animatorSet.setDuration(5000);
    animatorSet.start();

这样就实现了一个文本框文字放大和旋转同时进行的动画效果,但是这里用到了 AnimatorSet 以及创建了两个 ObjectAnimator 类对象,那么我们来看用 PropertyValuesHolder 来实现

PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
PropertyValuesHolder pvhRTextSize = PropertyValuesHolder.ofKeyframe("textSize", kf3, kf4, kf5);
ObjectAnimator rotationAndSizeAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation,pvhTextSize)
rotationAnim.setDuration(5000ms);

这样就只需要一个 ObjectAnimator 类对象就好了

更多关于 PropertyValuesHolder 请查看官方文档
https://developer.android.com/reference/android/animation/PropertyValuesHolder.html
更多关于 Keyframe 请查看官方文档
https://developer.android.com/reference/android/animation/Keyframe.html#setValue(java.lang.Object)

Animating Views##

在第一篇的时候有跟大家说过 补间动画 只能改变 view 的图形,而实际并没有动。这是因为在以前额的API版本里面,动画的效果的实现是通过改变它们图像界面的绘制来实现的,并没有真正地改变 view 的属性。在 Android 3.0后,view 增加了很多的属性以及增加了对应的 getter 和 setter 方法,于是也就有了 属性动画 ,从而消除上述的弊端。

新增加的属性:

  • translationX and translationY: 这两个参数控制 view 在容器中的位置,一个控制 x 轴方向,一个控制 y 轴方向。它们两个是一个差值,大小定义为 view 的实际坐标 x,y 减去在开始在容器里面设置的 x0,y0,也就是 translationX/Y = x/y -x0/y0
  • rotation, rotationX, and rotationY: 这些参数控制 view 在2D平面和在3D平面上的旋转,并且是围绕中心点旋转的
  • scaleX and scaleY: 这些参数控制 view 围绕中心点进行2D平面上的缩放
  • pivotX and pivotY: 这些参数控制 view 的中心点,默认为 view 图像的中心点,也是rotation 动画和 scale 动画进行时的中心点
  • x and y: view 在容器中的实际坐标
  • alpha: 代表控件的透明度,范围1~0,默认为1,0表示完全透明

Animating with ViewPropertyAnimator##

ViewPropertyAnimator 顾名思义,是专门用于 view 的动画类。回顾一下之前讲得内容,可以看到,我们要实现一个 view 的动画效果,都是要新建一个 Animator 类,然后再把目标 view 当做参数传到它里面,这样其实是很不符合认得思维习惯。我们正常的思维习惯是,有一个 view ,然后我们可以通过 view 的子方法调用来时动画。比如想要一个 view 实现 x 方向的移动,那么就可以是

    view.x(50);

实际上,Android官方就提供 ViewPropertyAnimator 类来满足上述的要求。它比起直接新建一个 Animator 类的有事在于

  1. 它可以直接用 view 通过调用特定的方法,比如 .x(50) 就可以实现动画效果,尽管底层仍是调用 Animator 来实现动画效果,但是我们不需要理会系统是怎样实现的,保证了代码的简洁和易读性
  2. 在对 view 执行多个动画的时候,如果是用 Animator 类来实现的话,每一个属性的改变都会去调用 invalidate() 方法,这样系统处理起来就不够好,降低性能。但是使用 ViewPropertyAnimator ,它会自动计算出调用 invalidate() 的最优时间,提高性能。

下面我们来对比一下几种对一个 view 实现多个动画的方法

Multiple ObjectAnimator objects

ObjectAnimator animX = ObjectAnimator.ofFloat(myView, "x", 50f);
ObjectAnimator animY = ObjectAnimator.ofFloat(myView, "y", 100f);
AnimatorSet animSetXY = new AnimatorSet();
animSetXY.playTogether(animX, animY);
animSetXY.start();

One ObjectAnimator

PropertyValuesHolder pvhX = PropertyValuesHolder.ofFloat("x", 50f);
PropertyValuesHolder pvhY = PropertyValuesHolder.ofFloat("y", 100f);
ObjectAnimator.ofPropertyValuesHolder(myView, pvhX, pvyY).start();

ViewPropertyAnimator

myView.animate().x(50f).y(100f);

更多关于 ViewPropertyAnimator 请查看官方文档
https://developer.android.com/reference/android/view/ViewPropertyAnimator.html

Declaring Animations in XML##

属性动画 允许我们用 XML 文件的形式创建动画。通过 XML 文件创建动画,我们就可以在多个Activity 里面重用这些动画。并且对动画进行修改,只需要修改 XML 文件就可以修改所有的使用这个 XML 文件的动画。

这个 XML 文件必须放在 res/animator/ 目录下,也就意味着你要在 res 里面新建一个 animator 文件夹,然后在里面新建你的 XML 文件

定义动画 XML 的标签有如下三个:

  • ValueAnimator - < animator >
  • ObjectAnimator - < objectAnimator >
  • AnimatorSet - < set >

使用 XML 动画的步骤:

  1. 在 res/animator/ 目录下创建一个 XML 文件,并编写代码。在这个目录下,这个 XML 文件会自动在 R文件里的 animator 类中生成一个 id 来表示它,这里我们命名 XML 为 property_animator ,则它的 id 就为 R.id.property_animator
  2. 然后就需要在代码中调用它,方法是在代码中定义一个 AnimatorSet 类,然后通过 AnimatorInflater 类的 loadAnimator( Context context , int id ) 来解析 XML 里定义的动画,并传到 AnimatorSet 对象中
  3. 最后为这个 AnimatorSet 对象通过 setTarget( Object Target ) 来设置需要进行该动画的目标

例子:

property_animator.xml

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <set>
        <objectAnimator
            android:duration="500"
            android:propertyName="x"
            android:valueTo="400"
            android:valueType="intType" />
        <objectAnimator
            android:duration="500"
            android:propertyName="y"
            android:valueTo="300"
            android:valueType="intType" />
    </set>
    <objectAnimator
        android:duration="500"
        android:propertyName="alpha"
        android:valueTo="0f" />
</set>

code

    AnimatorSet animatorSet =(AnimatorSet) AnimatorInflater.loadAnima(this,
    R.animator.property_anim);
    animatorSet.setTarget(button);
    animatorSet.start();

至此,关与属性动画所有的知识已经结束,在下面给出的链接是官方关于属性动画的API demo
https://android.googlesource.com/platform/development/+/654f51a/samples/ApiDemos/src/com/example/android/apis/animation?autodive=0%2F/

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

推荐阅读更多精彩内容