属性动画(Property Animation)

补间动画只能定义起始和结束两个帧在“透明度”、“旋转”、“倾斜”、“位移”4个方面的变化,逐帧动画也只能是播放多个图片,无法满足我们日常复杂的动画需求,所以谷歌在3.0开始,推出了属性动画(property animation)

属性动画已经不再是针对View来设计的了,也不仅限定于只能实现移动、缩放、淡入淡出这几种动画操作,同时也不再是一种视觉上的动画效果了。它实际上是一种不断的对值进行操作的机制,并将值赋值到指定对象的指定属性上,可以是任意对象的任意属性。

ValueAnimator

ValueAnimator是整个属性动画机制中最核心的一个类,负责计算动画的起始值和结束值之间的动画过度,我们只需要把起始值和结束值以及运行时间提供给ValueAnimator,ValueAnimator会自动计算出从起始值到结束值之间的过度值。另外ValueAnimator还负责管理动画的播放此时,播放模式,以及设置监听器等

例如我们需要在2秒内将值从0过度到5再过度到0的动画,我们就可以这样写:

public class MainActivity extends Activity implements OnClickListener {

    private ImageView iv;
    private Button bt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        iv = (ImageView) findViewById(R.id.image);
        bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt:
            ValueAnimator va = ValueAnimator.ofFloat(0f, 5f, 0f);
            va.setDuration(1000);
            va.addUpdateListener(new AnimatorUpdateListener() {
                @Override
                public void onAnimationUpdate(ValueAnimator animation) {
                    float i = (float) animation.getAnimatedValue();
                    Log.d("TTTT", "运行时间:" + i);
                }
            });
            va.start();
            break;
        }
    }
}

在上面的代码中通过addUpdateListener()方法添加了一个动画监听器,在动画执行的过程中会不断的回调onAnimationUpdate方法,在这个方法中将当前的值打印出来,会发现系统自动计算了中间过度过程的值

ObjectAnimator

ValueAnimator是对过度值进行了一个计算,ObjectAnimator则可以直接对任意对象属性进行动画操作

譬如我们想要将一个图片3秒内从透明变成常规再变成透明

public class MainActivity extends Activity implements OnClickListener {

    private ImageView iv;
    private Button bt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        iv = (ImageView) findViewById(R.id.image);
        bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt:
            ObjectAnimator oa = ObjectAnimator.ofFloat(iv, "alpha", 0f, 1f, 0f);
            oa.setDuration(3000);
            oa.start();
            break;
        }
    }
}

ofFloat的参数说明:

  • target:传入我们要操作的对象

  • propertyName:传入要操作的对象属性

  • values:想要实现的动画值(长度不固定)

常用的动画属性:

  • rotation——旋转

  • translationX——X轴方向位移

  • translationY——Y轴方向位移

  • scaleX——X轴方向缩放

  • scaleY——Y轴方向缩放

AnimatorSet

通过名字就可以看出这个类是用来实现动画集合的,这个类可以帮助我们将多个动画组合起来一起播放。

AnimatorSet提供了一个play()方法,如果我们向这个方法中传入一个Animator对象(ValueAnimator或ObjectAnimator)将会返回一个AnimatorSet.Builder的实例,AnimatorSet.Builder中包括以下四个方法:

  • after(Animator anim) 将现有动画插入到传入的动画之后执行

  • after(long delay) 将现有动画延迟指定毫秒后执行

  • before(Animator anim) 将现有动画插入到传入的动画之前执行

  • with(Animator anim) 将现有动画和传入的动画同时执行

譬如我们要实现图片在移动的同时旋转

public class MainActivity extends Activity implements OnClickListener {

    private ImageView iv;
    private Button bt;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        initView();
    }

    private void initView() {
        iv = (ImageView) findViewById(R.id.image);
        bt = (Button) findViewById(R.id.bt);
        bt.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {
        case R.id.bt:
            ObjectAnimator traslationAnimator = ObjectAnimator.ofFloat(iv, "translationX", -600f, 0f);
            ObjectAnimator rotationAnimator = ObjectAnimator.ofFloat(iv, "rotation", 0f, 360f);

            AnimatorSet as = new AnimatorSet();
            as.play(rotationAnimator).with(traslationAnimator);
            as.setDuration(3000);
            as.start();
            break;
        }
    }
}

Animator监听器

在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。

大家已经知道,ObjectAnimator是继承自ValueAnimator的,而ValueAnimator又是继承自Animator的,因此不管是ValueAnimator还是ObjectAnimator都是可以使用addListener()这个方法的。另外AnimatorSet也是继承自Animator的,因此addListener()这个方法算是个通用的方法。

添加一个监听器的代码如下所示:

anim.addListener(new AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
    }

    @Override
    public void onAnimationEnd(Animator animation) {
    }

    @Override
    public void onAnimationCancel(Animator animation) {
    }
});

可以看到,我们需要实现接口中的四个方法,onAnimationStart()方法会在动画开始的时候调用,onAnimationRepeat()方法会在动画重复执行的时候调用,onAnimationEnd()方法会在动画结束的时候调用,onAnimationCancel()方法会在动画被取消的时候调用。

但是也许很多时候我们并不想要监听那么多个事件,可能我只想要监听动画结束这一个事件,那么每次都要将四个接口全部实现一遍就显得非常繁琐。没关系,为此Android提供了一个适配器类,叫作AnimatorListenerAdapter,使用这个类就可以解决掉实现接口繁琐的问题了,如下所示:

anim.addListener(new AnimatorListenerAdapter() {  
});  

这里我们向addListener()方法中传入这个适配器对象,由于AnimatorListenerAdapter中已经将每个接口都实现好了,所以这里不用实现任何一个方法也不会报错。那么如果我想监听动画结束这个事件,就只需要单独重写这一个方法就可以了,如下所示:

anim.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationEnd(Animator animation) {
    }
});

转自郭霖博客:http://blog.csdn.net/guolin_blog/article/details/43536355

Copyright© 2020-2022 li-xyz 冀ICP备2022001112号-1