Android动画篇——属性动画ValueAnimator类简单使用

因为这两周在外面实训,所以很少有更新文章了,新的知识也没有心思再去学习了,所以就决定回顾温习一下以前学习过的知识。虽然这两天实训做的是用C语言做游戏,但是发现有些写代码的思想还是很值得我们借鉴的,而且还可以锻炼我们的思维,所以说无论我们做什么事情都是对我们有所提高的。

好啦,扯皮到此结束哈哈,下面进入正题。


属性动画中对应的两个大类:ObjectAnimator和ValueAnimator。有的朋友之前用过这两个类,其实如果仔细观察的话,会发现他们两个是继承关系(ValueAnimator继承ObjectAnimator)。

今天给大家带来的文章是关于属性动画中的其中一个类——ValueAnimator

目录

ValueAnimator原理

常用方法

创建方法

ValueAnimator监听器

ValueAnimator使用



ValueAnimator原理

在上面我们也提到了,ValueAnimator是属性动画中的其中一个类,根据他的名字也可以看出来,他是对值进行操作的一个类。在它内部有一个循环机制,我们只需要添加起始值、结束值和时长,在内部的循环机制会根据这三个值来进行起始到结束的动画过渡。

简单来说就是我们给ValueAnimator分配三个属性:起始值、结束值、动画时长,一旦启动了这个动画,ValueAnimator内部会不断地循环来获取每一时刻的属性值。我们可以根据获取到的数值进行一系列操作。


常用方法

//设置属性值
public void setFloatValues(float... values);
public void setIntValues(int... values);
public void setObjectValues(Object... values);
public void setValues(PropertyValuesHolder... values);


public void start();//启动动画
public void cancel();//取消动画
public void pause();//暂停动画
public void end();//结束动画
public void resume();//继续动画
public void reverse();//反向播放动画


public ValueAnimator setDuration(long duration);//设置动画时间
public void setRepeatCount(int value);//设置动画重复的次数
public void setRepeatMode(@RepeatMode int value);//设置动画重复模式:正向播放和反向播放


public void setEvaluator(TypeEvaluator value);//设置估值器
public void setInterpolator(TimeInterpolator value);//设置插值器(这两个后面再讲)

创建方法

一般情况下我们都是通过new创建对象,对于ValueAnimator(还有ObjectAnimator)而言,创建动画实例对象是通过ValueAnimator提供的有参工厂去创建动画实例:

ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f,50f,200f);

上面是通过ofFloat创建的实例对象,0、50、200对应的都是float类型的数据。

对于上面所说的从起始到结束的数据,如果有超过两个变量的赋值,那么代表的就是每相邻两个值为起始结束值的过渡。

就上面的例子来说,最开始的起始值是0,结束时是50f,等到达50时,起始值为50f,结束值为200f。你懂我意思吧。

当前除了ofFloat方法之外,还有很多创建方法,主要分为三类:

  • ofFloat、ofInt、ofArgb
  • ofObject
  • ofPropertyValuesHolder

第一类是通过基本数据值创建ValueAnimator(第三个ofArgb对颜色填入的也是基础数据,所以我将它也归为这一类),我们每一时刻获取到的数据值都为基本数据类型。

第二类是起始值、结束值、每一时刻获取到的数据都为一个Object对象。

第三类是通过填入PropertyValuesHolder创建ValueAnimator对象。(这个在以后会介绍)

由于今天是第一次接触ValueAnimator,所以先只用第一类来创建,剩下的在以后会给大家说明的。

ValueAnimator监听器

在上面说到,ValueAnimator是不断获取当前时刻的值,这个不断获取值就是通过监听器(AnimatorUpdateListener)回调得到的,使用如下:

valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
         //.......       
    }
});

通过创建AnimatorUpdateListener监听器,在其里面的onAnimationUpdate回调方法中有一个参数animation。我们可以通过ValueAnimator的getAnimatedValue方法获取到当前时刻的属性值。ValueAnimator两个重载方法:

Object getAnimatedValue();
Object getAnimatedValue(String propertyName);

一般是使用第一个方法,第二个中propertyName参数为指定的属性名,一般是对于一个ValueAnimator设置多个属性变换的时候才会添加propertyName(以后再说这个)。

接下来用代码实现一下上面的功能:

valueAnimator = ValueAnimator.ofFloat(0f,50f,100f);

valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
    @Override
    public void onAnimationUpdate(ValueAnimator animation) {
        float value = (float) animation.getAnimatedValue();
        Log.e(TAG, "onAnimationUpdate: "  + value);
    }
});

findViewById(R.id.start).setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        valueAnimator.start();
    }
});

给ValueAnimator设置从0到50再到100,然后设置时间为2s。然后添加属性更新监听器,在onAnimationUpdate里面获取到属性值,在日志中打印出来。

设置按钮的点击事件,启动动画。

根据上面所说的,应该是在每一个时间点都会获得对应时刻的属性值,也就是不断地在回调的onAnimationUpdate方法中获取属性值,效果如下:

我们可以看到在日志中是不断地获取到当前的属性值。

除了更新监听器之外,ValueAnimator还有两个监听器:AnimatorListener和AnimatorPauseListener。分别为动画监听器和中断监听器。

AnimatorListener负责监听ValueAnimator的状态:启动(start)、结束(end)、取消(cancel)、重复(repeat),当动画执行到对应的步骤时回调对应的四个方法:

valueAnimator.addListener(new Animator.AnimatorListener() {
    @Override
    public void onAnimationStart(Animator animation) {
        //在动画首次启动的时候进行回调,对应ValueAnimator.start();
    }

    @Override
    public void onAnimationEnd(Animator animation) {
        //当动画自行执行完毕或手动执行ValueAnimator.end();时回调
    }

    @Override
    public void onAnimationCancel(Animator animation) {
        //在动画取消时回调,对应ValueAnimator.cancel();
    }

    @Override
    public void onAnimationRepeat(Animator animation) {
        //在动画每次重复执行时候回调
    }
});

可能这里有的朋友会问这cancel和end有什么区别,他俩的区别大了去了:

对于ValueAnimator.end();方法,如果执行end方法

AnimatorPauseListener负责动画的暂停监听,当动画暂停(pause)时、继续(resume)时,进行回调:

valueAnimator.addPauseListener(new Animator.AnimatorPauseListener() {
    @Override
    public void onAnimationPause(Animator animation) {
        //当动画暂停时回调,对应方法ValueAnimator.panse();
    }

    @Override
    public void onAnimationResume(Animator animation) {
        //当动画由暂停状态继续时回调,对应方法ValueAnimator.resume();
    }
});

有时候我们可能只需要一个方法回调,比如我们想要回调onAnimationStart方法,但是在重写AnimatorListener时候会重写四个方法,显得代码多了很多无用的事情,这时候我们就需要另一个类——AnimationListenerAdapter

public abstract class AnimatorListenerAdapter implements Animator.AnimatorListener,
    Animator.AnimatorPauseListener

AnimatorListenerAdapter是一个抽象类,他实现了AnimatorListener和AnimatorPauseListener两个接口,实现了两个接口的总共6个方法,不过方法为空,所以我们如果我们只想要实现一个状态的回调,可以通过AnimatorListenerAdapter类达到效果。

valueAnimator.addListener(new AnimatorListenerAdapter() {
    @Override
    public void onAnimationStart(Animator animation) {
        super.onAnimationStart(animation);

    }
);

好了,关于监听器就说到这里了,剩下的几种状态机监听,大家下去自行实验吧。

ValueAnimator使用

上我们确实看到了不同的时刻一个数值的不断变化,但是上面这个好像是跟动画没什么关系的额,但是仔细想一下,如果我们将每一时刻获取到的数值赋值给一个对象的属性,那么这回对象就会不断地变化。

也就是说,我们只是获取到一个不断变化的值,而这个值最后是具体干什么的,完全由我们自己来决定:

一般情况下对于动画的操纵主要有四种:平移(translation)、旋转(rotate)、缩放(scale)、透明度(alpha)。对应方法如下:

public void setTranslationX(float translationX);//x方向偏移
public void setTranslationY(float translationY);//y方向偏移
public void setTranslationZ(float translationZ);//z方向偏移

public void setScaleX(float scaleX);//x方向缩放
public void setScaleY(float scaleY);//y方向缩放


public void setRotation(float rotation);//以垂直手机平面的中心点为轴旋转
public float setRotationY(float rotationY);//以y轴(水平中心)为旋转轴旋转
public void setRotationX(float rotationX)l//以x轴(竖直中心)为旋转轴旋转

public void setAlpha(@FloatRange(from=0.0, to=1.0) float alpha);//设置透明度:0.0为全透明,1.0为不透明

注意到我上面说的是针对对象,而不单单是一个控件,这也同时说明了属性动画针对的是对象的属性,而不仅仅局限于是View的属性。(可能刚刚接触的朋友还不太理解这句话的含义,随着使用就会慢慢了解的。)

最后我们举一个例子来使用ValueAnimator:

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


        valueAnimator = ValueAnimator.ofFloat(0f, 90f, -90f);

        valueAnimator.setDuration(2000);
        valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float value = (float) animation.getAnimatedValue();
                start.setRotation(value);
            }
        });

        start = findViewById(R.id.start);
        start.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                valueAnimator.start();
            }
        });


    }

我们实现了一个两秒之内,让Button按钮先旋转到顺时针90°,然后逆旋转到逆时针90°位置。效果如下:

好了,关于ValueAnimator的初次使用就介绍到这里了,相信大家看到这里已经会初步使用ValueAnimator类了。关于属性动画的文章笔者会不断更新的。希望大家多多支持。

猜你喜欢

转载自blog.csdn.net/zy_jibai/article/details/81091425