美文网首页
Android动画之ObjectAnimator中ofXX函数全

Android动画之ObjectAnimator中ofXX函数全

作者: sliencexiu | 来源:发表于2019-08-05 00:23 被阅读0次

    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<T, Integer> 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<T, Float> property, float... values) api14可用
    ofFloat(T target, Property<T, Float> xProperty, Property<T, Float> 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<T, Integer> property, int... values) api14可用
    ofInt(T target, Property<T, Integer> xProperty,Property<T, Integer> 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<T, float[]> converter, TypeEvaluator<T> 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<T, int[]> converter, TypeEvaluator<T> evaluator, T... values)    api21可用
    
    ofObject(Object target, String propertyName,
                @Nullable TypeConverter<PointF, ?> converter, Path path)  api21可用
    ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)  api11
    ofObject(T target, Property<T, P> property,
                TypeConverter<V, P> converter, TypeEvaluator<V> evaluator, V... values)  api21
    ofObject(T target, @NonNull Property<T, V> property,
                @Nullable TypeConverter<PointF, V> converter, Path path)   api2可用
    ofObject(T target, Property<T, V> property, TypeEvaluator<V> 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<T, Float> property, float... values)
    ofFloat(T target, Property<T, Float> xProperty, Property<T, Float> yProperty, Path path)
    
    ofInt(Object target, String propertyName, int... values)
    ofInt(Object target, String xPropertyName, String yPropertyName,Path path)
    ofInt(T target, Property<T, Integer> property, int... values)
    ofInt(T target, Property<T, Integer> xProperty,Property<T, Integer> 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();
    

    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();
    

    上面的示例代码利用了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();
    

    ofFloat(T target, Property<T, Float> 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<View, Float> ROTATION = new FloatProperty<View>("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();
    

    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<TextView,String>{
        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<String>{
    
        @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();
    
    

    ofFloat(T target, Property<T, Float> xProperty, Property<T, Float> 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();
    

    ofArgb(T target, Property<T, Integer> property, int... values)

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

    public static class MyProperty extends Property<TextView,Integer>{
        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();
    

    4 ofMultiFloat,ofMultiInt

    被称为多参数布局,用的不太多,下面简单介绍:
    ofMultiFloat(Object target, String propertyName,float[][] values)
    ofMultiFloat(Object target, String propertyName, Path path)
    ofMultiFloat(Object target, String propertyName,
    TypeConverter<T, float[]> converter, TypeEvaluator<T> evaluator, T... values)
    ofMultiInt(Object target, String propertyName, int[][] values)
    ofMultiInt(Object target, String propertyName, Path path)
    ofMultiInt(Object target, String propertyName,
    TypeConverter<T, int[]> converter, TypeEvaluator<T> 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();
    

    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();
    

    ofMultiInt(Object target, String propertyName,TypeConverter<T, int[]> converter, TypeEvaluator<T> 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 <Point ,int[]>{
        public IntConverter(Class<Point> fromClass, Class<int[]> toClass) {
            super(fromClass, toClass);
        }
    
        @Override
        public int[] convert(Point value) {
            int[] intarr = {value.getX(),value.getY()};
            return intarr;
        }
    }
    

    自定义估值器:

    public static class PointEvaluator implements TypeEvaluator<Point> {
    
        @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();
    

    5 ofObject

    对对象进行动画:

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

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

    ofObject(T target, Property<T, V> property, TypeEvaluator<V> 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<TextView,Point>{
        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<Point> {
    
        @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();
    

    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();
    

    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函数全

          本文链接:https://www.haomeiwen.com/subject/xhukdctx.html