安卓动画(三)--属性动画

属性动画

在前面学习了安卓的帧动画和补间动画,其实那两种动画都属于一类,并没有对VIew的属性进行了改变,就是靠视觉效果来展现动画的,所以就出现了属性动画
这里写图片描述
为啥要有属性动画
1逐帧动画和补间动画只能作用于视图上,只可以对一个Button,TextView,,,或者继承View的组件进行操作,但无法对非view的对象进行操作
2没有改变view的属性,只是改变了视觉效果
3动画效果单一

工作原理:在一定时间内,不断对值进行变化,然后将值赋值给对象的属性//对象的任意属性这里写图片描述
所以这里面有两个关键类,还是两种实现方式,一种java方式,一直xml方式,但这里推荐java方式,因为很多属性和起始值都不能在xml里面获取,需要在java里面获取
//xml模式 采用animator标签

ValueAnimator 手动赋值
ObjectAnimator 自动赋值

ValueAnimator类

这里写图片描述
其实这个原理也蛮简单,
设定好对象属性初始值和结束值,
通过插值器和估值器来设定变化的逻辑规律,根据规律不断改变值,然后每当值改变一遍,就手动赋值给对象属性值一次
不断刷新视图 绘制视图
如果初始值等于结束值 就结束了

从上面原理可以看出:ValueAnimator类中有3个重要方法:
ValueAnimator.ofInt(int values)
ValueAnimator.ofFloat(float values)
ValueAnimator.ofObject(int values)

ValueAnimator.ofInt(int values)

作用:将初始值 以整型数值的形式 过渡到结束值
这里写图片描述

下面是个例子 按钮测试一的宽度变化
这里写图片描述

private Button mButton;
private ValueAnimator valueAnimator;//整形估值器

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    //创建动画对象
    mButton = (Button)findViewById(R.id.btn_play);
    //1设置属性数值的初始值和结束值
    valueAnimator = ValueAnimator.ofInt(mButton.getLayoutParams().width,500);
    //初始值 = 当前按钮的宽度
    //结束值 = 500
    //ValueAnimator.ofInt()里面内置了整形估值器,默认看如何变化

    //2设置动画的各种属性
    valueAnimator.setDuration(2000);
    valueAnimator.setRepeatCount(5);

    //3将属性数值手动赋值给对象的属性 这里是将值付给按钮的宽度
    //更新监听器,数值每次变化都会调用这个方法

    valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
        @Override
        public void onAnimationUpdate(ValueAnimator animation) {
            int currentValue = (int) animation.getAnimatedValue();
            //获取每次变化的值

            mButton.getLayoutParams().width = currentValue;
            //每次赋值

            mButton.requestLayout();
            //4刷新视图。重新绘制

        }
    });
    //5启动动画
    valueAnimator.start();

}

过程代码上都有
1创建动画对象
2设置属性数值的初始值和结束值
3设置动画的各种属性
4使用监听器,然后只要变化就给属性赋值
5刷新视图
6启动动画

ValueAnimator.oFloat(float values)

作用:将初始值 以浮点型数值的形式 过渡到结束值

这里写图片描述
ValueAnimator.ofInt()与ValueAnimator.oFloat()仅仅只是在估值器上的区别:(即如何从初始值 过渡 到结束值)
ValueAnimator.oFloat()采用默认的浮点型估值器 (FloatEvaluator)
ValueAnimator.ofInt()采用默认的整型估值器(IntEvaluator)

过程和上面的一样 不再讲了

ValueAnimator.ofObject()

作用:将初始值 以对象的形式 过渡到结束值
这个和上面两个还不太一样,这个初始值是初始动画的对象,结束值是结束动画的对象

// 创建初始动画时的对象  & 结束动画时的对象
myObject object1 = new myObject(); 
myObject object2 = new myObject();
ValueAnimator anim = ValueAnimator.ofObject(new myObjectEvaluator(), object1, object2); 
// 创建动画对象 & 设置参数
// 参数说明
// 参数1:自定义的估值器对象(TypeEvaluator 类型参数) - 下面会详细介绍
// 参数2:初始动画的对象
// 参数3:结束动画的对象
anim.setDuration(5000); 
anim.start();

估值器(TypeEvaluator)

作用:设置动画 如何从初始值 过渡到 结束值 的逻辑
插值器(Interpolator)决定 值 的变化模式(匀速、加速blabla)
估值器(TypeEvaluator)决定 值 的具体变化数值
先看下估值器其实是个接口

public interface TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue)

参数:fraction 动画完成度
startValue 动画初始值
endValue 动画结束值
目的:要返回当前完成度的值
计算方式:目前值 = 初值+完成度*(结束值-初始值)
下面有个例子 自定义了一个小球对象 成员变量是坐标x和y值 然后自定义插值器

public class PointEvaluator implements TypeEvaluator {
    @Override
    public Object evaluate(float fraction, Object startValue, Object endValue) {
        //讲动画的初始值和结束值强制转换为Point对象
        Point startPoint = (Point)startValue;
        Point endPoint = (Point)endValue;

        //根据fraction来计算当前的x和y的值
        float x = startPoint.getX()+fraction*(endPoint.getX()-startPoint.getX());
        float y = startPoint.getY()+fraction*(endPoint.getY()-startPoint.getY());
        //将算好的坐标封装好给一个新的Point对象并返回
        Point point = new Point(x,y);
      return point;
    }
}

ObjectAnimator类

直接对对象的属性值进行改变操作,从而实现动画效果
如直接改变 View的 alpha 属性 从而实现透明度的动画效果
继承自ValueAnimator类,即底层的动画实现机制是基ValueAnimator类
本质原理: 通过不断控制 值 的变化,再不断 自动 赋给对象的属性,从而实现动画效果
这里写图片描述
从上面的工作原理可以看出:ObjectAnimator与 ValueAnimator类的区别:
ValueAnimator 类是先改变值,然后 手动赋值 给对象的属性从而实现动画;是 间接 对对象属性进行操作;
ObjectAnimator 类是先改变值,然后 自动赋值 给对象的属性从而实现动画;是 直接 对对象属性进行操作;

这个用java里面设置特别快我们使用了属性动画最基本的四种动画效果:透明度、平移、旋转 & 缩放
即在ObjectAnimator.ofFloat()的第二个参数String property传入alpha、rotation、translationX 和 scaleY 等blabla
自动赋给对象的属性的本质是调用该对象属性的set() & get()方法进行赋值
所以,ObjectAnimator.ofFloat(Object object, String property, float ….values)的第二个参数传入值的作用是
让ObjectAnimator类根据传入的属性名 去寻找 该对象对应属性名的 set() & get()方法
看下效果图
这里写图片描述

 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main3);
        button1 = (Button)findViewById(R.id.btn_ow1);
        button2 = (Button)findViewById(R.id.btn_ow2);
        button3 = (Button)findViewById(R.id.btn_ow3);
        button4 = (Button)findViewById(R.id.btn_ow4);
        button5 = (Button)findViewById(R.id.btn_ow5);
        button6 = (Button)findViewById(R.id.btn_ow6);
        //第一个透明度
        ObjectAnimator animator = ObjectAnimator.ofFloat(button1,"alpha",1f,0f,1f);
        //第一个参数是动画的对象 第二个是操作的对象的属性 第三个是初始值 最后一个是结束的值
        animator.setDuration(5000);
        animator.setRepeatCount(-1);
        animator.start();

       //第二个旋转
        ObjectAnimator animator1 = ObjectAnimator.ofFloat(button2,"rotation",0f,360f);
        animator1.setDuration(5000);
        animator1.setRepeatCount(-1);
        animator1.start();

        //第三个平移
        float curTranslationX = button3.getTranslationX();
        float curTranslationX1 = button6.getTranslationX();
        //获取当前位置
        ObjectAnimator animator2 = ObjectAnimator.ofFloat(button3,"translationX",curTranslationX,300,curTranslationX);
        animator2.setDuration(5000);
        animator2.setRepeatCount(-1);
        animator2.start();
        //第四个缩放
        ObjectAnimator animator3 = ObjectAnimator.ofFloat(button4,"scaleX",1f,3f,1f);
        animator3.setDuration(5000);
        animator3.setRepeatCount(-1);
        animator3.start();
        //第五个 组合动画的java方式
//        //组合动画
//        ObjectAnimator translation = ObjectAnimator.ofFloat(button6,"translationX",curTranslationX1,300,curTranslationX1);
//        ObjectAnimator rotate = ObjectAnimator.ofFloat(button6,"rotation",0f,365f);
//        ObjectAnimator alpha = ObjectAnimator.ofFloat(button6,"alpha",1f,0f,1f);
//        //创建组合动画的对象
//        AnimatorSet animatorSet = new AnimatorSet();
//        //根据组合动画对象组合
//        animatorSet.play(translation).with(rotate).before(alpha);
//        animatorSet.setDuration(5000);
//
//        animatorSet.start();
        //第五个 组合动画的xml方式
        AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this,R.animator.set2_animation);
        animatorSet.setTarget(button6);
        animatorSet.start();



        button5.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent2 = new Intent(Main3Activity.this,Main4Activity.class);
                startActivity(intent2);
            }
        });




    }

组合模式的xml 在res/animator 里面建立的 跟标签是set

<?xml version="1.0" encoding="utf-8"?>
<set xmlns:android="http://schemas.android.com/apk/res/android"
    android:ordering="sequentially">
    <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"/>
    </set>

    <set
        android:ordering="sequentially">

        <objectAnimator
            android:duration="1500"
            android:propertyName="alpha"
            android:valueFrom="1"
            android:valueTo="0"
            android:valueType="floatType"/>
        <objectAnimator
            android:duration="1500"
            android:propertyName="alpha"
            android:valueFrom="0"
            android:valueTo="1"
            android:valueType="floatType"/>
    </set>
</set>

实现步骤:
也是两种方式 一种java一种xml方式
java方式:
1创建ObjectAnimator对象
ObjectAnimator animator = ObjectAnimator.ofFloat(button1,”alpha”,1f,0f,1f);
//第一个参数是动画的对象 第二个是操作的对象的属性 第三个是初始值 最后一个是结束的值
2设置动画的其他属性 比如时间啊 循环次数
3启动动画
xml方式
1.在xml 在res/animator 里面建立的xml文件 如果是组合动画 跟标签是set
2在java代码里面创建对象//下面是组合属性动画的对象AnimatorSet
AnimatorSet animatorSet = (AnimatorSet) AnimatorInflater.loadAnimator(this,R.animator.set2_animation);
//参数 上下文,xml
animatorSet.setTarget(button6);
//绑定控件
animatorSet.start();
//启动动画

总结

属性动画也就是这些内容,可能自定义插值器那块有点难,其他的都还行,蛮有意思的嘻嘻

猜你喜欢

转载自blog.csdn.net/sakurakider/article/details/80313250