android动画系列(一):property属性动画

来源:互联网 发布:织梦dedecms建站教程 编辑:程序博客网 时间:2024/05/16 16:01

Property 动画

与view动画的区别

  1. view动画只能作用于view,而property动画的作用范围更广
  2. view动画只能作用于缩放,平移,淡化,旋转这几个特性,对于别的比如背景颜色的改变不能作用
  3. view动画只是改变了view的绘制,并没有改变view的实际属性,所以“只是看上去好看而已”,而property动画解决了这个问题
    由官网上的介绍来说,就是 任何属性,任何对象(看得到或者看不到),任何时候。

属性

下列属性可以更改
duration,Time interpolation,Repeat count and behavior,Animator sets,Frame refresh delay

监听原理

1.计算已完成动画分数
首先,new 一个ValueAnimator,然后为要修改的属性指定开始,结束的值,这样的话,ValueAnimator会一直计算随着时间的减少value的值变化的百分率,
2.计算插值分数
当valueAnimator计算完之后,他会去调用TimeInterpolator,去计算得到一个插值分数,当然传入的是当前的已完成动画分数

  /**     * Maps a value representing the elapsed fraction of an animation to a value that represents     * the interpolated fraction. This interpolated value is then multiplied by the change in     * value of an animation to derive the animated value at the current elapsed animation time.     *     * @param input A value between 0 and 1.0 indicating our current point     *        in the animation where 0 represents the start and 1.0 represents     *        the end     * @return The interpolation value. This value can be more than 1.0 for     *         interpolators which overshoot their targets, or less than 0 for     *         interpolators that undershoot their targets.     */    float getInterpolation(float input);

3.计算属性值
当插值分数计算完成后,valueAnimator会调用合适的TypeEvaluator来计算运动中的函数值,这是TypeEvaluator的返回值,我们以floatEvaluator为例

@Override    public float[] evaluate(float fraction, float[] startValue, float[] endValue) {        float[] array = mArray;        if (array == null) {            array = new float[startValue.length];        }        for (int i = 0; i < array.length; i++) {            float start = startValue[i];            float end = endValue[i];            array[i] = start + (fraction * (end - start));        }        return array;    }

这里传进去的就是fraction:插值分数,startValue:初始值,endValue:结束值。从而我们可以计算出来并返回对象属性现在的值

总结一下就是:ValueAnimator以时间为基准获得elapsed fraction,然后插值器通过时间的流失率获得动画的变化率,这个变化率就是作用于我们的属性的。最后typeEvaluator通过动画变化率得到属性的当前值

使用方法

ValueAnimator

整个property 动画有两个步骤:
1.首先是计算出属性的值
2.然后是为对象属性设置这些值,即应用和刷新动画

我们通过ValueAnimator完成了第一个步骤,如果要完成第二个步骤需要监听由ValueAnimator计算得到的属性值,并修改目标对象。需要实现ValueAnimator .onUpdateListener 接口,自己去处理对象的动画逻辑

ValueAnimator animation = ValueAnimator.ofFloat(0f, 1f);animation.setDuration(1000);animation.addUpdateListener(new AnimatorUpdateListener() {@Overridepublic void onAnimationUpdate(ValueAnimator animation) {        Log.i("update", ((Float) animation.getAnimatedValue()).toString());      }});animation.setInterpolator(new CycleInterpolator(3));animation.start();

ObjectAnimator

objectAnimator是valueAnimator的子类,它比valueAnimator好的地方就是它不用自己去写对象属性的处理逻辑,只需要我们将对象和对象的一个属性传入就行了。
但是有如下限制:

  • The object property that you are animating must have a setter function (in camel case) in the form of set().
    如果没有的话,有三个方法来解决它:1.Add the setter method to the class if you have the rights to do so. 2.Use a wrapper class that you have rights to change and have that wrapper receive the value with a valid setter method and forward it to the original object. 3.Use ValueAnimator instead.
  • the object property that you are animating must have a getter function that is used to obtain the starting value of the animation. The getter function must be in the form of get()。之所以需要一个get方法,是因为当我们只传入了一个value时,他会作为endvalue,所以为了获取startValue,必须有这个方法,不然没有办法实现效果。
  • 属性值要对应一致
  • Depending on what property or object you are animating, you might need to call the invalidate() method on a View to force the screen to redraw itself with the updated animated values. 也就是为了更新界面,必须调用这个方法。我们在onAnimationUpdate中调用。

TimeInterplotar与TypeEvaluator的区别

通过系统给出来的例子,很多都是在timeInterplotor中获取到变化率,然后在TypeEvaluator中进行简单的数学运算。其实他们两个中都可以进行变化率的计算,并且TypeEvaluator还可以进行返回。最主要的区别是TypeEvaluator中可以获取三个参数而TimeInterpolator只能获得一个参数。所以如果有些时候需要用到startValue和endValue,我们就需要使用TypeEvaluator来定义变换方法。

ViewpropertyAnimator

可以方便的为某个View的多个属性添加并行的动画,只使用一个ViewPropertyAnimator对象就可以完成。它的行为更像一个ObjectAnimator,因为它修改的是对象的实际属性值。但它为一次性给多个属性添加动画提供了方便,而且使用ViewPropertyAnimator的代码更连贯更易读。
下面是使用多个Objectanimator,一个Objectanimator,一个ViewPropertyanimator的区别

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

一个ObjectAnimator和多个PropertyValuesHolder相结合

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);//myView.animate()直接返回一个ViewPropertyAnimator对象

补充:propertyValuesHolder的属性设置

PropertyValuesHolder pvsX = PropertyValuesHolder.ofFloat(“scaleX”, 1f, 0.7f);
PropertyValuesHolder tlSWY = PropertyValuesHolder.ofFloat(“translationY”, -50f, 0f);
PropertyValuesHolder apSWY = PropertyValuesHolder.ofFloat(“alpha”, 0.25f, 1f);
PropertyValuesHolder roSWXY = PropertyValuesHolder.ofFloat(“rotation”, -25f, 0f);
第一个是初始值,第二个是end值(并且是以你的初始设置或者在xml中的位置或大小作为参考值0或1),translation以下右为正,rotation以顺时针为正,逆时针为负。

keyFrame

keyframe是由一个键值对组成,可以定制动画在某一特定时间点的特定状态。可以有自己的插值器,用于控制自己前一帧和后一帧的动画

keyframe.ofFloat(0.5f,300f)

第一个参数是时间参数,第二个参数是属性值。这个keyframe可以很好解决ObjectAnimator等无法精确控制时间点的动画的情况。
当我们给animator设置插值器时,我们是给整体进行的设置,但是我们仍然可以为这个时间点即keyframe对象设置插值器。

使用方法:

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(5000);

XML中定义Animator

xml文件中支持这三者:
- valueAnimator:
- objectAnimator:
- AnimatorSet:

<set android:ordering="sequentially">    <set>        <objectAnimator            android:propertyName="x"            android:duration="500"            android:valueTo="400"            android:valueType="intType"/>        <objectAnimator            android:propertyName="y"            android:duration="500"            android:valueTo="300"            android:valueType="intType"/>    </set>    <objectAnimator        android:propertyName="alpha"        android:duration="500"        android:valueTo="1f"/></set>// 然后可以这样使用AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(myContext,    R.anim.property_animator);set.setTarget(myObject);set.start();
0 0
原创粉丝点击