#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



    
        
        
    
    

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/

你可能感兴趣的:(#Android 动画之属性动画(四)#)