Android动画效果之Property Animation(属性动画)

一. Property Animation产生的背景:

    由于Tween Animation(补间动画)只能实现简单的四种的动画(alpha、scale、rotate、translate),要想实现比较复杂的动画就难以满足需求,而且补间动画只是改变了View对象绘制的位置,而没有改变View对象本身,比如View形状的变换,如大小的缩放,透明度的改变,位置的改变,其实本身并没有改变,举个例子就好比孙悟空灵魂出窍一样,虽然已经上天入地,其实肉体还在那里一动不动,我们开发过程中的经常遇见的就是translate之后事件还在原地。如果要实现既要有动画效果又要使得View本身得到真正改变,那就要借助属性动画了,这也是属性动画引入的原因。它能够更加灵活的实现各种效果,不仅限于类似补间动画实现的哪几种效果。

(1)Property Animation相关类

   属性动画,根据字面理解可以通过修改物件的属性值以达到动画效果。

类名 用途
ValueAnimator 属性动画主要的计时器,也计算动画后的属性的值,动画的执行类
ObjectAnimator   ValueAnimator的一个子类,允许你设置一个目标对象和对象的属性进行动画,动画的执行类
AnimatorSet 提供组织动画的结构,使它们能相关联得运行,用于控制一组动画的执行
AnimatorInflater  用户加载属性动画的xml文件
Evaluators  属性动画计算器,告诉了属性动画系统如何计算给出属性的值
Interpolators 动画插入器,定义动画的变化率

(2)Interpolator(插值器)

   Interpolator插值器用于控制动画的变化速率,也可以简单的理解成用于控制动画的快慢,插值器目前都只是对动画执行过程的时间进行修饰,并没有对轨迹进行修饰。系统提供的插值器有以下几种:

插值器名字 解说 对应的xml
AccelerateInterpolator  加速,开始时慢中间加速  @android:anim/accelerate_interpolator
DecelerateInterpolator 减速,开始时快然后减速 @android:anim/decelerate_interpolator
AccelerateDecelerateInterolator   先加速后减速,开始结束时慢,中间加速  @android:anim/accelerate_decelerate_interpolator
AnticipateInterpolator 反向 ,先向相反方向改变一段再加速播放  @android:anim/anticipate_interpolator
AnticipateOvershootInterpolator 反向加超越,先向相反方向改变,再加速播放,会超出目的值然后缓慢移动至目的值 @android:anim/anticipate_overshoot_interpolator
BounceInterpolator  跳跃,快到目的值时值会跳跃,如目的值100,后面的值可能依次为85,77,70,80,90,100 @android:anim/bounce_interpolator
CycleIinterpolator  循环,动画循环一定次数,值的改变为一正弦函数:Math.sin(2* mCycles* Math.PI* input) @android:anim/cycle_interpolator
LinearInterpolator  线性,线性均匀改变 @android:anim/linear_interpolator
OvershootInterpolator 超越,最后超出目的值然后缓慢改变到目的值 @android:anim/overshoot_interpolator

二. 使用ObjectAnimator

(1)alpha渐变效果

         1>java代码实现

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "alpha", 1.0f, 0.1f);    //绑定布局,设置为渐变,从1.0 --> 0.1
animator.setDuration(2000);        //设置动画时间
animator.setRepeatCount(10);        //设置动画显示次数
animator.setRepeatMode(ValueAnimator.REVERSE);    //设置动画显示模式,反向
animator.setStartDelay(200);        //设置动画多次显示的时间间隔
animator.setInterpolator(new OvershootInterpolator());    //设置动画插入器,插入器直接影响显示结果
animator.start();                    //开始动画

2>xml实现

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="alpha"
    android:duration="3000"
    android:repeatCount="1"
    android:repeatMode="reverse"
    android:startOffset="200"
    android:valueFrom="1.0"
    android:valueTo="0.1"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(2)scale翻转效果(与补间动画scale有些区别)

1>java代码实现

 
 
 
 
ObjectAnimator animator = ObjectAnimator
        .ofFloat(image, "scaleX", 1.0f, 0.1f);  //scaleX为Y轴不变,以view中心为点,X轴翻转;scaleY效果相反
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml实现

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="scaleX"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="1.0"
    android:valueTo="0.1"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(3)rotation 旋转效果(与补间动画rotate书写不一样)

1>java代码实现

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f);  //旋转角度0 --> 360
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml实现

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="rotation"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="0f"
    android:valueTo="360f"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(4)translation(与补间动画translate书写不一样)

1>java代码实现

//translationX,Y轴不变,水平X轴移动,0f为屏幕中心,0f --> 480f(水平向右移动);translationY,X轴不变,水平Y轴移动
ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 480f); 
animator.setDuration(2000);
animator.setRepeatCount(10);
animator.setRepeatMode(ValueAnimator.REVERSE);
animator.setStartDelay(200);
animator.setInterpolator(new OvershootInterpolator());
animator.start();

2>xml实现

<?xml version="1.0" encoding="utf-8"?>
<objectAnimator xmlns:android="http://schemas.android.com/apk/res/android"
    android:propertyName="translationY"
    android:repeatCount="10"
    android:repeatMode="restart"
    android:valueFrom="0f"
    android:valueTo="480f"
    android:duration="2000"
    android:startOffset="200"
    android:valueType="floatType">

</objectAnimator>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

(5)set

1>java代码实现(旋转向右移动)

①使用AnimatroSet实现

AnimatorSet animatorSet = new AnimatorSet();

ObjectAnimator animator = ObjectAnimator.ofFloat(image, "translationX", 0f, 400f);
animator.setRepeatMode(ValueAnimator.REVERSE);    //动画模式,需要单独设置
animator.setRepeatCount(10);                      //动画次数n+1次,需要单独设置

ObjectAnimator animator1 = ObjectAnimator.ofFloat(image, "rotation", 0f, 360f);
animator1.setRepeatMode(ValueAnimator.REVERSE);   //动画模式,需要单独设置
animator1.setRepeatCount(10);                     //动画次数n+1次,需要单独设置

animatorSet.setDuration(2000);                    //动画时间,可set设置
animatorSet.setStartDelay(200);                   //动画间隔,可set设置
animatorSet.playTogether(animator,animator1);     //set添加动画
animatorSet.setInterpolator(new OvershootInterpolator());
animatorSet.start();

②使用PropertyValuesHolder实现

PropertyValuesHolder scaleXValuesHolder = PropertyValuesHolder.ofFloat("scaleX", 1.0f, 0.1f);
PropertyValuesHolder scaleYValuesHolder = PropertyValuesHolder.ofFloat("alpha", 1.0f, 0.1f);
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(image, scaleXValuesHolder, scaleYValuesHolder);
objectAnimator.setDuration(2000);
objectAnimator.setRepeatCount(10);
objectAnimator.setRepeatMode(ValueAnimator.REVERSE);
objectAnimator.start();

③使用ViewPropertyAnimator实现

ViewPropertyAnimator viewPropertyAnimator=image.animate();
viewPropertyAnimator.scaleXBy(1.0f).scaleX(0.1f).alphaBy(1.0f).scaleY(0.1f).setDuration(2000).start();

2>xml实现

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android">
    <objectAnimator
        android:duration="2000"
        android:propertyName="translationX"
        android:repeatCount="10"
        android:repeatMode="reverse"
        android:startOffset="200"
        android:valueFrom="0f"
        android:valueTo="400f"
        android:valueType="floatType" />
    <objectAnimator
        android:duration="2000"
        android:propertyName="rotation"
        android:repeatCount="10"
        android:repeatMode="reverse"
        android:startOffset="200"
        android:valueFrom="0f"
        android:valueTo="360f"
        android:valueType="floatType" />

</set>
Animator animator = AnimatorInflater.loadAnimator(this, R.animator.object1_layout);
animator.setTarget(image);
animator.start();

三. ObjectAnimator的监听事件

(1)ObjectAnimator.addListener

有时候我们可能要在某一个动画执行之前 或者动画结束之后进行一些其他的操作

ObjectAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animator) {
        //TODO 动画开始前的操作
        Log.i("aaaaa", "动画开始前的操作");
    }

    @Override
    public void onAnimationEnd(Animator animator) {
        //TODO 动画结束的操作
        Log.i("aaaaa", "动画结束的操作");
    }

    @Override
    public void onAnimationCancel(Animator animator) {
        //TODO 动画取消的操作
        Log.i("aaaaa", "动画取消的操作");
    }

    @Override
    public void onAnimationRepeat(Animator animator) {
        //TODO 动画重复的操作
        Log.i("aaaaa", "动画重复的操作");
    }
});

(2)objectAnimator.addUpdateListener

如果我们需要简单动画执行过程中的变化可以使用AnimatorUpdateListener

 
 
ObjectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        float value = (float) animator.getAnimatedValue();
        Log.i("aaaaa", "valueAnimator : " + value);
        if (value >= 300 && value <= 320)
            Toast.makeText(AnimatorActivity.this, value + "", Toast.LENGTH_SHORT).show();
    }
});

四. ValueAnimator(差值动画)

ValueAnimator是ObjectAnimator的父类,它继承自抽象类Animator,它作用于一个值,将其由一个值变化为另外一个值,然后根据值的变化,按照一定的规则,动态修改View的属性,比如View的位置、透明度、旋转角度、大小等,即可完成了动画的效果。

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 12164f);
valueAnimator.setDuration(5000);
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator valueAnimator) {
        float money = (float) valueAnimator.getAnimatedValue();
        textView.setText(String.format("%.2f", money));
    }
});
valueAnimator.start();

每天进步一点点!

猜你喜欢

转载自blog.csdn.net/qq_26446715/article/details/79865208