Android属性动画的用法

本文详细介绍了Android属性动画的四种用法:ValueAnimator类、ObjectAnimator的使用、AnimatorSet的组合动画以及ViewPropertyAnimator的直接操作。通过示例代码解释了ValueAnimator的ofFloat和ofObject方法,以及ObjectAnimator的便捷性。还提到了AnimatorSet用于组合动画,并展示了ViewPropertyAnimator的常见应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

属性动画有两个非常重要的类:ValueAnimator类和ObjectAnimator类,后者继承于前者,属性动画的实现基本也是靠这两个类

一.ValueAnimator类

ValueAnimator类是属性动画中最核心的一个类,其工作原理是:通过控制值的不断变化,然后根据值的变化不断地去改变目标的属性,最终达到动画效果。主要方法有:ValueAnimator.ofInt(int... values)、ValueAnimator.onFloat(float... values)、ValueAnimator.ofObject(TypeEvaluator evaluator, Object... values)三种。下面来介绍一下ofFloat方法

1.1 ValueAnimator.ofFloat(float... values)

ofFloat方法返回一个ValueAnimator对象,可以接受多个float类型的参数,看看它的简单使用方式

        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
                view.requestLayout();
            }
        });

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

在动画监听器中将变化的属性值打印出来,如下:

可以看到,动画值是在300毫秒内从0增加到10的,然后在变化过程中,通过不断地改变view的属性并渲染View,从而呈现出动画效果,另外ofInt方法的使用方式也是一样的,只是参数类型不同而已

 

1.2  ValueAnimator.ofObject(TypeEvaluator evaluator, Object... values)的使用

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

定义一个类Point作为Object参数,它代表的是一个坐标,如下

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),插值器是用来反映动画变化规律的,比如线性变化,先变大后变小等等,估值器是基于插值器的变化规律,不断地改变自定义的那个Object的相关值,说到底动画就是体现某些不断变化的值,所以说变化是动画的灵魂,下面来实现一个自定义的估值器:

public class PointEvaluator implements TypeEvaluator<Point> {

    @Override
    public Point evaluate(float fraction, Point startValue, Point endValue) {
        //通过返回的动画速率fraction,去改变Object的值
        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实例,第一个参数是自定义的估值器
        ValueAnimator animator=ValueAnimator.ofObject(new PointEvaluator(),startPoint,endPoint);
        animator.setDuration(5000);
        animator.setStartDelay(300);
        //监听value的变化
        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                //获得自定义估值器中evaluate方法返回的Point对象,代表当前的变化值
                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();
    }

在上面onAnimationUpdate中,通过animation.getAnimatedValue()返回的point就是我们在估值器PointEvaluator的evaluate方法计算得到的那个对象,通过这个变化的Point对象去改变x值和y值,ofObject本质上还是对值的操作, 只是将这些操作都封装在对象里面。效果图如下

 

二.ObjectAnimator的使用

ObjectAnimator是在ValueAnimator的基础对动画操作做了封装,它与ValueAnimator的最大区别是,ValueAnimator需要自己手动改变对象的属性,而ObjectAnimator直接设置对象的属性和其他参数即可实现动画,所以ObjectAnimator更方便

ObjectAnimator的基本使用示例:

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

ObjectAnimator其实它里面还是用ObjectAnimator来实现的,在它的ofFloat方法中,第一个参数是动画的目标view,第二个参数是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

 

三.AnimatorSet 的使用

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" >
    // 动画执行顺序的属性值: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代码中使用xml定义的动画,如下

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

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

 

四.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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值