Android属性动画的用法

版权声明:本文为博主石月的原创文章,转载请注明出处 https://blog.csdn.net/liuxingrong666/article/details/84061933

Android中动画的实现方式有三种:属性动画、补间动画、逐帧动画。其中属性动画是指在一定的时间间隔内,通过对给予对象的属性值的改变而达到动画效果,相比于其他两种动画方式,其灵活性要大很多。而补间动画的实现,通常是局限于view对象,而且并不能改变view的属性,只是通过改变视觉效果来达到动画效果,这种局限使得补间动画的效果单一,无法跟属性动画相媲美。所以学好属性动画,对我们及其重要。

属性动画有两个非常重要的类:ValueAnimator类和ObjectAnimator类,其中后者继承于前者,属性动画的实现基本也是靠这两个类,下面我们分别来介绍这两个类是怎么来实现动画效果的。

1.ValueAnimator类

ValueAnimator类是属性动画中最核心的一个类,其工作原理是:通过不断控制值的变化,然后根据值的变化不断地去改变对象的属性,从而达到动画效果。其主要方法有,ValueAnimator.ofInt(itn value)、ValueAnimator.onFloat(float value)、ValueAnimator.ofObject(object value)三种。下面我们先来介绍ofFloat方法。

1.1 ValueAnimator.ofFloat(float value)

具体使用方式,可以用java代码设置,也可用xml文件设置,下面我们来看看代码设置方式是如何使用的:

        ValueAnimator animator = ValueAnimator.ofFloat(0, 10);
        //设置动画时长
        animator.setDuration(300);
        //设置动画执行延迟时间
        animator.setStartDelay(100);
        //设置动画重复次数
        animator.setRepeatCount(0);
        //设置动画重复模式
        animator.setRepeatMode(ValueAnimator.RESTART);

        //设置动画监听器,值的改变都会回调
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                float currentValue = animation.getAnimatedValue();
                LogUtils.d("当前动画值=" + currentValue);

                //改变view的属性值
                view.setProperty(currentValue);
                view.requestLayout();
            }
        });

        //开始动画
        animator.start();

上面我们简单地展示了ValueAnimator的使用,我们在动画监听器那里将动画值的变化打印出来,如下:

从上面可以看到,动画值是在300毫秒内从0增加到10的,然后在这里值的变化过程中,我们不断地对view的属性进行改变,就可以让view产生动画效果了。

 

1.2  ValueAnimator.ofObject(object value)的使用

 这个方法跟上面的ofFloat有所不同,上面改变的对象直接是float值,而这个是针对Object对象,是针对所有的对象的,所以属性动画的灵活性就在这里了,而这object对象是需要开发者自己定义的。下面我们通过一个实例去解析如何使用ofObject方法。

我们属性定义一个Object类为Point,代表一个坐标,如下

public class Point {

    float x;
    float y;

    public Point(float x, float y) {
        this.x = x;
        this.y = y;
    }

    public float getX() {
        return x;
    }

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

    public float getY() {
        return y;
    }

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

我们先来讲解一下估值器(TypeEvaluator)和插值器(Interpolator),插值器是用来反映动画变化规律的, 估值器是基于插值器的那个变化规律,根据自己的需求计算得出返回的数据值。下面我们来实现一个自定义估值器:

public class PointEvaluator implements TypeEvaluator<Point> {

    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {

        float x = startValue.getX() + (endValue.getX() - startValue.getX()) * fraction;
        float y = startValue.getY() + (endValue.getY() - startValue.getY()) * fraction;
        Point point = new Point(x, y);
        return point;
    }
}

下面我们来实现一个需求,将一个button从手机屏幕的左上角通过属性动画移动到屏幕的右下角,这个button的初始位置为屏幕的左上角。看看代码

public void ofObjectBtn(Context context, final Button button) {

        //起初点
        Point startPoint = new Point(0, 0);
        //终点
        Point endPoint = new Point(Utils.getScreenWidth(context)-220, Utils.getScreenHeight(context)-200);

        ValueAnimator animator=ValueAnimator.ofObject(new PointEvaluator(),startPoint,endPoint);
        animator.setDuration(5000);
        animator.setStartDelay(300);

        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {

                Point currentPoint= (Point) animation.getAnimatedValue();
                LogUtils.d("变化的值="+currentPoint.getX()+"///"+currentPoint.getY());
                FrameLayout.LayoutParams layoutParams= new FrameLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT);
                //改变btn的属性
                layoutParams.topMargin= (int) currentPoint.getY();
                layoutParams.leftMargin= (int) currentPoint.getX();
                button.setLayoutParams(layoutParams);
                button.requestLayout();
            }
        });

        animator.start();
    }

上面在监听器中,我们用getAnimatedValue方法返回是是Point对象,因为我们传入的values就是Point对象,而且这个返回的point就是我们在估值器PointEvaluator 中计算得到的对象。可以看出,ofObject本质上还是对值的操作, 只是将这些操作封装在一个对象中。效果图如下

 

2.ObjectAnimator的使用

1.1 ObjectAnimator是在ValueAnimator的基础对动画操作做了进一层的封装,它与ValueAnimator的最大区别是,ValueAnimator是手动赋值给对象属性而实现动画,ObjectAnimator是直接赋值给对象属性去实现动画,所以说ObjectAnimator更加方便、智能。

2.1 ObjectAnimator的基本使用如下示例:

//创建一个ObjectAnimator
ObjectAnimator animator = ObjectAnimator.ofFloat(targetView, propertyName, values ...);
 //设置插值器
animator.setInterpolator(interpolator);
//设置估值器
animator.setEvaluator(evaluator);
//设置时间间隔
animator.setDuration(values);
//开始动画
animator.start();

ObjectAnimator实现动画效果的本质是:通过不断控制值的变化,再不断赋值给对象的属性,从而实现动画。上面ofFloat方法中,第一个参数是动画的目标view,第二个是view的属性名字,values是指。我们来看看view的属性名称有哪些:

属性 作用 数值类型
Alpha 控制View的透明度 float
TranslationX 控制X方向的位移 float
TranslationY 控制Y方向的位移 float
ScaleX 控制X方向的缩放倍数 float
ScaleY 控制Y方向的缩放倍数 float
Rotation 控制以屏幕方向为轴的旋转度数 float
RotationX 控制以X轴为轴的旋转度数 float
RotationY 控制以Y轴为轴的旋转度数 float

ObjectAnimator会根据指定的属性名称,比如(TranslationX)去寻找目标对象的对应的get()和set()方法,因为View类中已经帮我实现了上面这些属性名称的get和set方法,所以如果target是view的话,就不用自己去定义了。ObjectAnimator的用法比较简单,我也就不具体举例子了。

 

3.AnimatorSet 的使用

这是一个组合动画使用的类,我们可以通过这个类将2个以上动画进行不同的组合,用法如下:

AnimatorSet.play(Animator anim)   :播放当前动画
AnimatorSet.after(long delay)   :将现有动画延迟x毫秒后执行
AnimatorSet.with(Animator anim)   :将现有动画和传入的动画同时执行
AnimatorSet.after(Animator anim)   :将现有动画插入到传入的动画之后执行
AnimatorSet.before(Animator anim) :  将现有动画插入到传入的动画之前执行

当然也可以用xml文件定义的形式来设置,anima_set文件如下:

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially" >
    // 表示Set集合内的动画按顺序进行
    // ordering的属性值:sequentially & together
    // sequentially:表示set中的动画,按照先后顺序逐步进行(a 完成之后进行 b )
    // together:表示set中的动画,在同一时间同时进行,为默认值

    <set android:ordering="together" >
        // 下面的动画同时进行
        <objectAnimator
            android:duration="2000"
            android:propertyName="translationX"
            android:valueFrom="0"
            android:valueTo="300"
            android:valueType="floatType" >
        </objectAnimator>
        
        <objectAnimator
            android:duration="3000"
            android:propertyName="rotation"
            android:valueFrom="0"
            android:valueTo="360"
            android:valueType="floatType" >
        </objectAnimator>
    </set>

        <set android:ordering="sequentially" >
            // 下面的动画按序进行
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="1"
                android:valueTo="0"
                android:valueType="floatType" >
            </objectAnimator>
            <objectAnimator
                android:duration="1500"
                android:propertyName="alpha"
                android:valueFrom="0"
                android:valueTo="1"
                android:valueType="floatType" >
            </objectAnimator>
        </set>

</set>

在java代码中启动动画如下:

        //以一个button为例
        mButton = (Button) findViewById(R.id.Button);
     
        //加载xml文件定义的动画
        AnimatorSet animator = (AnimatorSet) AnimatorInflater.loadAnimator(this, R.animator.set_animation);

        //设置目标
        animator.setTarget(mButton);
       
        animator.start()

 

4.ViewPropertyAnimator用法

直接操作动画属性从而实现动画,典型用法为:View.animate.xx(value).xx(value);用代码示例:

button.animate().alpha(0.5f).translationX(100).setDuration(100).start();
        
button.animate().alpha(0.5f).x(100).y(100);

好了,属性动画的用法就讲到这里了。其实我们着重理解那个估值器和插值器的使用方法,其他的都比较简单。

附上源码地址:石月的GitHub

 

 

猜你喜欢

转载自blog.csdn.net/liuxingrong666/article/details/84061933