Android 动画 ObjectAnimator基本使用

一.概述

之前讲了ValueAnimator,但是有个缺点,就是只能对数值对动画进行计算,我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作。这样使用起来相比补间动画而言就相对比较麻烦。
为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来,谷歌的开发人员在ValueAnimator的基础上,又派生了一个类ObjectAnimator。
由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。

但是ObjectAnimator也重写了几个方法,比如ofInt(),ofFloat(),我们先看看用ObjectAnimator的ofFloat如何实现一个动画。

1.使用

public class MainActivity extends ActionBarActivity {

    private TextView textView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        textView = (TextView) findViewById(R.id.textview);
    }
    public void start(View view){
        ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "alpha", 1,0,1);
        animator.setDuration(2000);
        animator.start();
    }
}

效果如下

这里写图片描述

我们这里使用的构造方法为

 public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

第一个参数为添加动画的对象
第二个参数为动画属性名称,这里我们使用alpha透明度动画
第三个参数为要改变的值,是可变的,这里我们从1变为0再变为1,也就是从不透明变成透明,然后变回来。

下面我们在看看如何实现旋转效果

public void start(View view){
        ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,0);
        animator.setDuration(2000);
        animator.start();
    }

效果如下:

这里写图片描述

从代码中可以看到,我们只需要改变ofFloat()的第二个参数的值就可以实现对应的动画。
那么问题来了,我们怎么知道第二个参数的值是啥呢?

2.set函数
我们在会看构造ObjectAnimator时的构造方法

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,0);

TextView有rotation这个属性吗,没有,连View中也没有,那它是怎么改变这个值的?其实,ObjectAnimator做动画,并不是根据控件xml中的属性来改变的,而是通过指定属性所对应的set方法来改变的。比如,我们上面指定的改变rotation的属性值,ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。同样的道理,当我们在最开始的示例代码中,指定改变”alpha”属性值的时候,ObjectAnimator也会到TextView中去找对应的setAlpha()方法。那TextView中都有这些方法吗,有的,这些方法都是从View中继承过来的,在View中有关动画,总共有下面几组set方法:

//1、透明度:alpha  
public void setAlpha(float alpha)  

//2、旋转度数:rotation、rotationX、rotationY  
public void setRotation(float rotation)  
public void setRotationX(float rotationX)  
public void setRotationY(float rotationY)  

//3、平移:translationX、translationY  
public void setTranslationX(float translationX)   
public void setTranslationY(float translationY)  

//缩放:scaleX、scaleY  
public void setScaleX(float scaleX)  
public void setScaleY(float scaleY)  

可以看到在View中已经实现了有关alpha,rotaion,translate,scale相关的set方法。所以我们在构造ObjectAnimator时可以直接使用。
1、要使用ObjectAnimator来构造对画,要操作的控件中,必须存在对应的属性的set方法
2、setter 方法的命名必须以骆驼拼写法命名,即set后每个单词首字母大写,其余字母小写,即类似于setPropertyName所对应的属性为propertyName
下面我们就来看一下上面中各个方法的使用方法及作用。

(1)setRotation,setRotationX,setRotationY

setRotation:绕z轴转

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,360);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

setRotationX:绕X轴转

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotationX", 0,180,360);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

setRotationY:绕Y轴转

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotationY", 0,180,360);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

(2) setTranslationX,setTranslationY
setTranslationX(float translationX):X方向移动的距离,以当前控件为原点,向右为正方向,参数translationX表示移动的距离。
setTranslationY(float translationY):
Y方向移动的距离,以当前控件为原点,向右为正方向,参数translationY表示移动的距离。

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationX", 0,200,-200,0);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

    ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationY", 0,200,-200,0);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

(3)setScaleX(float scaleX) :在X轴上缩放,scaleX表示缩放倍数
setScaleY(float scaleY) ::在Y轴上缩放,scaleY表示缩放倍数

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "scaleX", 0,3,2,0);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

我们可以看到,TextView在X方向从0倍变为3倍,然后变为2倍,最后又变为0倍,也就是消失了。

ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "scaleY", 0,3,2,0);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

二.原理

这里写图片描述

可以看到ObjectAnimator的动画流程中,也是首先通过加速器产生当前进度的百分比,然后再经过Evaluator生成对应百分比所对应的数字值。这两步与ValueAnimator是完全一样的,唯一不同的是最后一步,在ValueAnimator中,我们要通过添加监听器来监听当前数字值。而在ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字,比如这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到对应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(float scale)的参数将其传入。
这里在找到控件的set函数以后,是通过反射来调用这个函数的,
好了,在知道了ObjectAnimator的原理以后,下面就来看看如何自定义一个ObjectAnimator的属性吧。

三.自定义ObjectAnimator属性

这里写图片描述

我们自定义一个圆形,然后将它的半径从0变为3倍然后变为1倍,下面看看怎么实现
1.保存圆信息的Point类

public class Point {
    private float radius;

    public Point(float radius) {
        this.radius = radius;
    }

    public void setRadius(float radius) {
        this.radius = radius;
    }

    public float getRadius() {
        return radius;
    }
}

只有一个属性,就是半径

2.自定义的View,画一个圆形


public class MyPointView extends View{
    //创建圆形对象,半径为100
    private Point point = new Point(100);
    public MyPointView(Context context) {
        super(context);
    }
    public MyPointView(Context context, AttributeSet attrs) {
        super(context, attrs);
    }
    @Override
    protected void onDraw(Canvas canvas) {
        Paint paint = new Paint();
        paint.setColor(Color.RED);
        paint.setAntiAlias(true);
        paint.setStyle(Style.FILL);
        //以300,300为圆心,以当前圆的半径为半径,画一个圆
        canvas.drawCircle(300,300, point.getRadius(), paint);
        super.onDraw(canvas);
    }
    public void setPointRadius(float radius){
        point.setRadius(radius);
        invalidate();
    }
}

我们来看看这个setPointRadius方法:
第一点:这个方法对应的属性是pointRadius或者PointRadius,第一个字母大小写不是强制的,后面的字母必须与set函数一致
第二点:在setPointRadius中,先将当前动画传过来的值保存到mPoint中,做为当前圆形的半径。然后强制界面刷新
3.java代码,

public class MainActivity extends ActionBarActivity {

    private MyPointView pointView;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    pointView = (MyPointView) findViewById(R.id.pointview);
    }
    public void start(View view){
        ObjectAnimator animator = ObjectAnimator.ofFloat(pointView, "pointRadius", 0,300,100);
        animator.setDuration(2000);
        animator.start();
    }
}

我们可以看到,我们使用了pointRadius这个属性,对应的就是MyPointView类中的方法setPointRadius,点击按钮后,启动动画,ObjectAnimator就实时的把参数的值传递给setPointRadius这个函数,由于我们在这个函数中将半径设置给了圆形,然后重新绘制界面,所以可以看到圆的半径在不断变化。

3.何时需要实现对应属性的get函数
我们之前看到的ObjectAnimator的构造函数的第三个参数都是可变的,

 public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

那么我们如果传入一个参数会怎么样

    ObjectAnimator animator = ObjectAnimator.ofFloat(pointView, "pointRadius", 100);
        animator.setDuration(2000);
        animator.start();

这里写图片描述

我们可以看到,半径从0变为100,说明是从0开始变得,但是此时控制台已经给出了警告

这里写图片描述

为什么呢,因为当我们只设置一个值的时候,系统会调用get对应的属性值,如果找不到,就会使用默认的值开始动画,比如int类型为0,此时就会报出一个警告,如果给控件设置了get函数,就会从get函数对应的值开始动画。

public float getPointRadius(){
        return 50;
    }

这里写图片描述

我们可以看到,圆的半径是从50开始的,而不是0.
最后我们总结一下:当且仅当动画的只有一个过渡值时,系统才会调用对应属性的get函数来得到动画的初始值。

最后我们看看如何使用使用ArgbEvaluator

我们知道TextView有个属性可以改变背景颜色

public void setBackgroundColor(int color)

大家可以回想到,我们在ValueAnimator中也曾改变过背景色,使用的是ArgbEvaluator。在这里我们再回顾下ArgbEvaluator,它的实现代码如下:

public class ArgbEvaluator implements TypeEvaluator {  
    public Object evaluate(float fraction, Object startValue, Object endValue) {  
        int startInt = (Integer) startValue;  
        int startA = (startInt >> 24);  
        int startR = (startInt >> 16) & 0xff;  
        int startG = (startInt >> 8) & 0xff;  
        int startB = startInt & 0xff;  

        int endInt = (Integer) endValue;  
        int endA = (endInt >> 24);  
        int endR = (endInt >> 16) & 0xff;  
        int endG = (endInt >> 8) & 0xff;  
        int endB = endInt & 0xff;  

        return (int)((startA + (int)(fraction * (endA - startA))) << 24) |  
                (int)((startR + (int)(fraction * (endR - startR))) << 16) |  
                (int)((startG + (int)(fraction * (endG - startG))) << 8) |  
                (int)((startB + (int)(fraction * (endB - startB))));  
    }  
} 

这里主要说一下,ArgbEvaluator 返回值类型是int,所以我们要使用ofInt来实现动画

ObjectAnimator animator = ObjectAnimator.ofInt(textview, "backgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
        animator.setDuration(2000);
        animator.setEvaluator(new ArgbEvaluator());
        animator.start();

这里写图片描述

  • 13
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明 YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明YOLO高分设计资源源码,详情请查看资源内容中使用说明

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值