Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator

1 Android属性动画中ofXX函数概述

前面一篇属性动画文章中讲解了如何利用ObjectAnimator实现几种补间动画效果和如何自定义ObjectAnimator属性,其中用到了ObjectAnimator对象的ofInt,ofFLoat,ofObject,但这些函数都有众多的重载函数,这一篇接着讲解ObjectAnimator众多的ofXXX函数的用法。
观看本篇文章请务必先看Android动画之ValueAnimator用法和自定义估值器
ObjectAnimator of函数列表:

ofArgb(Object target, String propertyName, int... values)   api21可用
ofArgb(T target, Property property, int... values)  api21可用

ofFloat(Object target, String propertyName, float... values)  api11 可用
ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)   api21可用
ofFloat(T target, Property property, float... values) api14可用
ofFloat(T target, Property xProperty, Property yProperty, Path path)  api21可用

ofInt(Object target, String propertyName, int... values)  api11可用
ofInt(Object target, String xPropertyName, String yPropertyName,Path path) api21可用
ofInt(T target, Property property, int... values) api14可用
ofInt(T target, Property xProperty,Property yProperty, Path path) api21可用

ofMultiFloat(Object target, String propertyName,float[][] values)  api21可用
ofMultiFloat(Object target, String propertyName, Path path)        api21可用
ofMultiFloat(Object target, String propertyName,
            TypeConverter converter, TypeEvaluator evaluator, T... values)   api21可用
ofMultiInt(Object target, String propertyName, int[][] values)    api21可用
ofMultiInt(Object target, String propertyName, Path path)     api21可用
ofMultiInt(Object target, String propertyName,
            TypeConverter converter, TypeEvaluator evaluator, T... values)    api21可用

ofObject(Object target, String propertyName,
            @Nullable TypeConverter converter, Path path)  api21可用
ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)  api11
ofObject(T target, Property property,
            TypeConverter converter, TypeEvaluator evaluator, V... values)  api21
ofObject(T target, @NonNull Property property,
            @Nullable TypeConverter converter, Path path)   api2可用
ofObject(T target, Property property, TypeEvaluator evaluator, V... values)  api14可用

ofPropertyValuesHolder(Object target, PropertyValuesHolder... values)  api11可用

2 OfFloat & ofInt

把ofFLoat和ofInt两个函数一起讲解是因为这两个函数除了类型不一样,重载函数很相似。

ofFloat(Object target, String propertyName, float... values)
ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)
ofFloat(T target, Property property, float... values)
ofFloat(T target, Property xProperty, Property yProperty, Path path)

ofInt(Object target, String propertyName, int... values)
ofInt(Object target, String xPropertyName, String yPropertyName,Path path)
ofInt(T target, Property property, int... values)
ofInt(T target, Property xProperty,Property yProperty, Path path)

ObjectAnimator 的ofFloat和ofInt函数用法相似,所以只讲解ofFloat,

ofFloat(Object target, String propertyName, float... values)

这个函数比较简单,第一个参数传入目标对象,第二个参数传入要改变的属性(配合setXX函数,关于如何定义propertyName前面的文章中已经说明),第三个参数是个渐变属性,可以传多个值。
代码示例:
实现TextView的旋转:

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "rotation", 0, 270);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第1张图片

ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)

可以同时操纵两个参数变化,实现动画。
参数说明:
target:动画目标对象,这个目标对象有些特别,沿着一条路径Path能够使用两个属性,路径Path动画在二维空间中移动,由动画坐标(x,y)决定效果,(重要)所以对象必须有两个函数一个是setNameX(),另外一个是setNameY(),类似view的setTranslationX,SetTranslationY,当然也可以自己定义属性,同时对应的xPropertyName和yPropertyName分别为translationX和translationY。
xPropertyName:Path对应的X轴方向的属性值,
yPropertyName:Path对应的Y轴方向的属性值,
path:动画路径。

代码示例:
TextView 在X轴和Y轴方向上移动

Path path = new Path();
path.moveTo(0,0);
path.lineTo(50,50);
path.lineTo(100,20);
path.lineTo(900,400);
path.lineTo(500,1000);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "translationX","translationY",path );
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第2张图片

上面的示例代码利用了translationX和translationX属性,这两个属性是View的自带的属性,同时也可以是两个互不相干的属性,可以实现类似组合动画的效果。

Path path = new Path();
path.moveTo(0,0);
path.lineTo(50,1);
path.lineTo(100,2);
path.lineTo(900,0.5f);
path.lineTo(500,1);
ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, "translationX","scaleX",path );
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第3张图片

ofFloat(T target, Property property, float... values)

参数说明:
target:动画目标对象
property:动画作用的属性,有了这个属性对象, 就可以不用写属性对应的字段值,类似不用写“scale”
values:动画取值,如果是一个值则将target开始的状态作为开始值,将values的一个值,作为结束值,如果是两个值则第一个为动画开始值,第二个为动画结束值。

这个函数用到了Property属性,是API14添加的方法,不知道大家注意到没有,每次使用属性动画,我们都需要记得目标对象的setXXX函数后面的相应字符串,虽然不复杂但有时确实会记不清,需要再次确认,而这个带有Property的函数就大大简化了这个过程。

Android为我们提供了简单的常量对象来实现旋转动画:
ObjectAnimator.ofFloat(mTextView, View.ROTATION, 0,30);
这里的View.ROTATION就是个Property对象,可以简单地实现旋转的属性动画。

View.ROTATION源码

public static final Property ROTATION = new FloatProperty("rotation") {
    @Override
    public void setValue(View object, float value) {
        object.setRotation(value);
    }

    @Override
    public Float get(View object) {
        return object.getRotation();
    }
};

View.ROTATION示例

ObjectAnimator objectAnimator = ObjectAnimator.ofFloat(mTextView, View.ROTATION, 0,270);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第4张图片

View中具有和View.ROTATION作用的常量还有如下:
ALPHA,TRANSLATION_X,TRANSLATION_Y,TRANSLATION_Z,X,Y,ROTATION, ROTATION_X , ROTATION_Y,SCALE_X,SCALE_Y。

自定义Property

分析上面常量的他们都是实现了FloatProperty,或者IntProperty然后重写setValue和get方法,而FloatProperty,IntProperty又是继承了Property,所以我们可以通过实现FloatPropety,IntProperty或者直接实现Property来自定义Property。

自定义Property:

public static class MyProperty extends Property{
    public MyProperty(String name) {
        super(String.class, name);
    }

    @Override
    public String get(TextView object) {
        return object.getText().toString();
    }

    @Override
    public void set(TextView object, String value) {
        object.setText(value);
    }
}

自定义估值器:

public static class IntEvaluator implements TypeEvaluator{

    @Override
    public String evaluate(float fraction, String startValue, String endValue) {
        int startInt = Integer.parseInt(startValue) ;
        int endInt = Integer.parseInt(endValue);
        int cur = (int) (startInt + fraction * (endInt - startInt));
        return cur+"";
    }
}

使用自定义Property:

IntEvaluator intEvaluator = new IntEvaluator();
MyProperty property = new MyProperty("text");
ObjectAnimator objectAnimator = ObjectAnimator.ofObject(mTextView,property,intEvaluator,"1", "10");
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();

Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第5张图片

ofFloat(T target, Property xProperty, Property yProperty, Path path)
函数也用到了Property属性,需要结合property和Path,类似上面函数的用法,不再说明。

3 ofArgb 颜色属性动画

ofArgb(Object target, String propertyName, int... values) 对颜色属性进行动画。

参数说明:
target:动画作用对象
propertyName:动画作用的属性
values:动画使用的可变参数
代码示例:

ObjectAnimator objectAnimator = ObjectAnimator.ofArgb(mTextView,"backgroundColor", Color.RED, Color.GREEN);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第6张图片

ofArgb(T target, Property property, int... values)

用到了Property属性,但是View中没有类似ROTATION属性的对颜色属性的简写,可以自定义Property,下面的例子只是数值的渐变,如果真的需要颜色渐变,需要设置颜色估值器:

public static class MyProperty extends Property{
    public MyProperty(String name) {
        super(Integer.class, name);
    }

    @Override
    public Integer get(TextView object) {
        Drawable drawable =  object.getBackground();
        if (drawable instanceof ColorDrawable){
            return ((ColorDrawable) drawable).getColor();
        }
        return Color.YELLOW;
    }

    @Override
    public void set(TextView object, Integer value) {
        object.setBackgroundColor(value);
    }
}

使用:

MyProperty property = new MyProperty("background");
ObjectAnimator objectAnimator = ObjectAnimator.ofArgb(mTextView,property, Color.RED, Color.GREEN);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第7张图片

4 ofMultiFloat,ofMultiInt

被称为多参数布局,用的不太多,下面简单介绍:
ofMultiFloat(Object target, String propertyName,float[][] values)
ofMultiFloat(Object target, String propertyName, Path path)
ofMultiFloat(Object target, String propertyName,
TypeConverter converter, TypeEvaluator evaluator, T... values)
ofMultiInt(Object target, String propertyName, int[][] values)
ofMultiInt(Object target, String propertyName, Path path)
ofMultiInt(Object target, String propertyName,
TypeConverter converter, TypeEvaluator evaluator, T... values)
ofMultiFloat和ofMultiInt用法相似,由于上面只介绍了ofFloat,下面只介绍ofMultiInt方法:

ofMultiInt(Object target, String propertyName, int[][] values)

参数说明:
propertyName:进行动画的属性名
values[][]:二维数组,至少两组数据,每个values[]中存放一个setter函数中所有的参数,然后从values[0]中取值为动画开始值,从values[最后一组]中取值为动画最后的值,如果之间还有值,就作为过渡,从values[0]-values[1]-........(大家明白的)
需要自定义view添加getter,setter函数。

代码示例:

public class ViewDemo24 extends android.support.v7.widget.AppCompatTextView {

    public ViewDemo24(Context context) {
        this(context,null,0);
    }

    public ViewDemo24(Context context, @Nullable AttributeSet attrs) {
        this(context, attrs,0);
    }

    public ViewDemo24(Context context, @Nullable AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        init();
    }

    private void init() {
    }

    public void setMulText(int data1,int data2){
        String data = "";
       data = data + data1 + data2;
        setText(data);
    }

    public String getMulText(){
        return getText().toString();
    }
}

使用:

int[][] data = {{1,9},{4,12}} ;
ObjectAnimator objectAnimator = ObjectAnimator.ofMultiInt(viewDemo24,"mulText",data);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第8张图片

ofMultiInt(Object target, String propertyName, Path path)

用法和上面的函数类似,只不过把二维数组换成了Path,并且setter函数只能接收两个int参数,从path中取动画开始值和结束值(从path.moveTo中取动画开始值,后面的值为动画结束值)。
代码示例
**自定义view还用上面的ViewDemo24 **

Path path = new Path();
path.moveTo(0,6);
path.lineTo(5,9);
ObjectAnimator objectAnimator = ObjectAnimator.ofMultiInt(viewDemo24,"mulText",path);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第9张图片

ofMultiInt(Object target, String propertyName,TypeConverter converter, TypeEvaluator evaluator, T... values)

Converter:把int[]数组转换成需要的T类型,然后利用估值器计算T 得到ObjectAnimator需要的类型。

依然用上面的自定义view ,setter函数需要两个参数:
用到的自定义T类型:

public static class Point {
    int x;
    int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

自定义类型转换,把上面自定义的Point类型转换成int[]数组:

@RequiresApi(api = Build.VERSION_CODES.LOLLIPOP)
public static class IntConverter extends TypeConverter {
    public IntConverter(Class fromClass, Class toClass) {
        super(fromClass, toClass);
    }

    @Override
    public int[] convert(Point value) {
        int[] intarr = {value.getX(),value.getY()};
        return intarr;
    }
}

自定义估值器:

public static class PointEvaluator implements TypeEvaluator {

    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        int startxInt = startValue.getX() ;
        int endxInt = endValue.getX();
        int curx = (int) (startxInt + fraction * (endxInt - startxInt));

        int startyInt = startValue.getY() ;
        int endyInt = endValue.getY();
        int cury = (int) (startyInt + fraction * (endyInt - startyInt));
        Point point = new Point();
        point.setX(curx);
        point.setY(cury);
        return point;
    }
}

代码中使用:

IntConverter intConverter = new IntConverter(Point.class,int[].class);
PointEvaluator pointEvaluator = new PointEvaluator();
Point point1 = new Point();
point1.setX(1);
point1.setY(5);
Point point2 = new Point();
point2.setX(4);
point2.setY(9);
ObjectAnimator objectAnimator = ObjectAnimator.ofMultiInt(viewDemo24,"mulText",intConverter,pointEvaluator,point1,point2);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第10张图片

5 ofObject

对对象进行动画:

ofObject(Object target, String propertyName,
            @Nullable TypeConverter converter, Path path)
ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)
ofObject(T target, Property property,
            TypeConverter converter, TypeEvaluator evaluator, V... values)
ofObject(T target, @NonNull Property property,
            @Nullable TypeConverter converter, Path path)
ofObject(T target, Property property, TypeEvaluator evaluator, V... values)

上面讲解了ofInt ,ofFloat,ofMultiInt,ofMultiFloat等函数,仔细观察上面的ofObject函数,可以分析得到ofObject把类型泛型化了,每个函数都提供了TypeEvaluator供ObjectAnimator识别参数,所以ofObject的用法和ofInt,ofFloat相同。

ofObject(T target, Property property, TypeEvaluator evaluator, V... values)
参数说明:
target:动画目标对象
property:自定义property,内部调用getter,setter函数,不用再指定propertyName
evaluator:估值器,生成动画所需对象
values:动画传入参数

利用ofObject 实现view的移动
自定义类:

public static class Point {
    int x;
    int y;

    public int getX() {
        return x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return y;
    }

    public void setY(int y) {
        this.y = y;
    }
}

自定义property

public static class MyProperty2 extends Property{
    public MyProperty2(String name) {
        super(Point.class, name);
    }

    @Override
    public Point get(TextView object) {
        Point point = new Point();
        point.setX((int) object.getTranslationX());
        point.setY((int) object.getTranslationY());
        return  point;
    }

    @Override
    public void set(TextView object, Point value) {
        object.setTranslationX(value.getX());
        object.setTranslationY(value.getY());
    }
}

自定义Evaluator估值器

public static class PointEvaluator implements TypeEvaluator {

    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        int startxInt = startValue.getX() ;
        int endxInt = endValue.getX();
        int curx = (int) (startxInt + fraction * (endxInt - startxInt));

        int startyInt = startValue.getY() ;
        int endyInt = endValue.getY();
        int cury = (int) (startyInt + fraction * (endyInt - startyInt));
        Point point = new Point();
        point.setX(curx);
        point.setY(cury);
        return point;
    }
}

使用:

MyProperty2 property2 = new MyProperty2("tran");//參數只是为了标识无具体意义
PointEvaluator evaluator = new PointEvaluator();
Point point1 = new Point();
point1.setY(0);
point1.setX(100);

Point point2 = new Point();
point2.setY(700);
point2.setX(1000);
ObjectAnimator objectAnimator = ObjectAnimator.ofObject(mTextView,property2,evaluator,point1,point2);
objectAnimator.setDuration(3000);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.setRepeatCount(-1);
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第11张图片

6 ofPropertyValuesHolder(Object target, PropertyValuesHolder... values)

参数说明:
target:动画目标对象
values:PropertyValuesHolder 动画可变参数。
多动画执行,多个动画一起执行。

PropertyValuesHolder holder1 = PropertyValuesHolder.ofFloat("scaleX", 1,2);
PropertyValuesHolder holder2 = PropertyValuesHolder.ofFloat("scaleY",0, 1);
PropertyValuesHolder holder3 = PropertyValuesHolder.ofFloat("alpha", 0.5f,1.0f);

ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(mTextView, holder1, holder2, holder3);
objectAnimator.setDuration(3000);
objectAnimator.setRepeatCount(-1);
objectAnimator.setInterpolator(new LinearInterpolator());
objectAnimator.start();
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator_第12张图片

Keyframe 实现关键帧操作(来自Android Developer)
利用Keyframe可以添加一些关键帧,来控制动画的执行,例如:

Keyframe kf0 = Keyframe.ofFloat(0f, 0f);
Keyframe kf1 = Keyframe.ofFloat(.5f, 360f);
Keyframe kf2 = Keyframe.ofFloat(1f, 0f);
PropertyValuesHolder pvhRotation = PropertyValuesHolder.ofKeyframe("rotation", kf0, kf1, kf2);
ObjectAnimator rotationAnim = ObjectAnimator.ofPropertyValuesHolder(target, pvhRotation);
rotationAnim.setDuration(5000);

上面的代码作用为动画执行到一半时旋转360度,动画执行完时再从360旋转到0度。关键帧的作用和插值器的作用一样都是动画执行过程中,返回动画完成程度。
自定义插值器
ofXXX函数全部讲完了

Animation动画概述和执行原理
Android动画之补间动画TweenAnimation
Android动画之逐帧动画FrameAnimation
Android动画之插值器简介和系统默认插值器
Android动画之插值器Interpolator自定义
Android动画之视图动画的缺点和属性动画的引入
Android动画之ValueAnimator用法和自定义估值器
Android动画之ObjectAnimator实现补间动画和ObjectAnimator自定义属性
Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator
Android动画之AnimatorSet联合动画用法
Android动画之LayoutTransition布局动画
Android动画之共享元素动画
Android动画之ViewPropertyAnimator(专用于view的属性动画)
Android动画之Activity切换动画overridePendingTransition实现和Theme Xml方式实现
Android动画之ActivityOptionsCompat概述
Android动画之场景变换Transition动画的使用
Android动画之Transition和TransitionManager使用
Android动画之圆形揭露动画Circular Reveal
Android 动画之 LayoutAnimation 动画
Android动画之视图动画的缺点和属性动画的引入

你可能感兴趣的:(Android动画之ObjectAnimator中ofXX函数全解析-自定义Property,TypeConverter,TypeEvaluator)