您的位置:首页 > 移动开发 > Objective-C

Android 动画 ObjectAnimator基本使用

2016-02-14 11:28 741 查看

一.概述

之前讲了ValueAnimator,但是有个缺点,就是只能对数值对动画进行计算,我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作。这样使用起来相比补间动画而言就相对比较麻烦。

为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来,谷歌的开发人员在ValueAnimator的基础上,又派生了一个类ObjectAnimator。

由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。

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

1.使用

[code]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();
    }
}


效果如下



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

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


第一个参数为添加动画的对象

第二个参数为动画属性名称,这里我们使用alpha透明度动画

第三个参数为要改变的值,是可变的,这里我们从1变为0再变为1,也就是从不透明变成透明,然后变回来。

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

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


效果如下:



从代码中可以看到,我们只需要改变ofFloat()的第二个参数的值就可以实现对应的动画。

那么问题来了,我们怎么知道第二个参数的值是啥呢?

2.set函数

我们在会看构造ObjectAnimator时的构造方法

[code]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方法:

[code]//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轴转

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




setRotationX:绕X轴转

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




setRotationY:绕Y轴转

[code]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表示移动的距离。

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




[code]    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表示缩放倍数

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




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

[code]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类

[code]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,画一个圆形

[code]
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代码,

[code]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的构造函数的第三个参数都是可变的,

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


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

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




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



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

[code]public float getPointRadius(){
        return 50;
    }




我们可以看到,圆的半径是从50开始的,而不是0.

最后我们总结一下:当且仅当动画的只有一个过渡值时,系统才会调用对应属性的get函数来得到动画的初始值。

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

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

[code]public void setBackgroundColor(int color)


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

[code]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来实现动画

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


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: