Android开发Android开发经验谈Android技术知识

Android动画基础详析 | 属性动画基础及ValueAnim

2019-09-28  本文已影响0人  凌川江雪

为什么要引入属性动画

既然补间动画和逐帧动画已经很全了,为什么还要引入属性动画呢?

我们准备一个button和一个TextView,
首先给TextView控件添加了单击响应事件,
当单击该TextView时,会弹出Toast提示;
然后,
在单击按钮的时候,TextView控件开始向右下角移动。
从结果中可以看出,
在移动前,单击TextView控件是可以弹出Toast提示的;
而在移动后,单击TextView控件则没有响应,
相反,单击TextView控件原来所在的区域会弹出Toast提示。
这就说明补间动画虽然能对控件做动画,
但是并没有改变控件内部的属性值。

视图动画与属性动画的区别

从直观上来看,视图动画与属性动画有如下三点不同。
(1)引入时间不同:View Animation是在API Level 1时引入的;而Property Animation是在API Level 11时引入的,即从Android 3.0才开始有与Property Animation相关的API。
(2)所在包名不同:View Animation API在android.view.animation 包中,而Property Animation API在android.animation包中。
(3)动画类的命名不同:View Animation中的动画类命名都是XXXXAnimation,而Property Animation中的动画类命名都是XXXXAnimator。

动画属性

ValueAnimator

在上篇博客Android动画基础详析 | 概述、逐帧动画、视图动画(附诸多实际运行效果动图)的基础上我们新建一个property包和一个PropertyActivity:

activity_property.xml:

<?xml version="1.0" encoding="utf-8"?>
<RealativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".property.PropertyActivity">

    <Button
        android:id="@+id/btnValueAnimator"
        android:text="Go"
        android:onClick="onClick"
        android:layout_width = "match_parent"
        android:layout_height= "wrap_content"/> 

</RealativeLayout>

PropertyActivity.java:

public class PropertyActivity extends AppCompatActivity {

    private static final String TAG = "PropertyActivity";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_property);
    }

    public void onClick(View view){
        switch (view.getId()){
            case R.id.btnValueAnimator:
                ValueAnimator valueAnimator = ValueAnimator.ofInt(0,100);//ValueAnimator的正态方法ofInt,驱动整型数值
                valueAnimator.setDuration(100);//设置时长
                //设置属性刷新监听器
                valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                    @Override
                    public void onAnimationUpdate(ValueAnimator animation) {
                        //通过animation对象可以获取诸多动画相关属性

                        //获取当前的动画变化完成度,范围 0.0 - 1.0,0.0表示刚开始, 1.0表示完成
                        float animatedFracion = animation.getAnimatedFraction();
                        //获取当前状态基于正态方法的始末参数间的插值,强制转换的类型就看正态方法的数据类型;
                        int animatedValue = (int)animation.getAnimatedValue();
                        //打印这两个参数,其中%.3f即保留小数点后三位
                        Log.d(TAG, "onAnimationUpdate: "
                                + String.format("%.3f %d", animatedFracion,animatedValue));
                    }
                });
                valueAnimator.start();//开始动画
                break;
        }
    }
}

运行代码:

第一列数据是动画变化完成度,第二列数据是插值,
我们可以看到打印出来的值并不是线性的,???
因为ValueAnimator默认的插值器不是匀速的;???
下面给ValueAnimator设置插值器即可:

...
valueAnimator.setDuration(100);//设置时长
                valueAnimator.setInterpolator(new LinearInterpolator());//设置插值器
                //设置属性刷新监听器
...

ValueAnimator的简单使用案例

  • ValueAnimator只负责对指定值区间进行动画运算;
    我们需要对运算过程进行监听,然后自己对控件执行动画操作。

  • ofInt()与ofFloat()的唯一区别就是传入的数值类型不一样,ofInt()函数需要传入Integer类型的参数,而ofFloat()函数则需要传入Float类型的参数。

    它们的参数类型都是可变长参数,所以我们可以传入任何数量的值;
    传进去的值列表就表示动画时的变化范围,
    比如ofInt(2,90,45)就表示从数字2变化到数字90再变化到数字45,
    所以我们传进去的数字越多,
    动画变化就越复杂。

getAnimatedValue()函数的声明Object getAnimatedValue();
它返回的是Object原始类型,
那我们怎么知道要将它转换成什么类型呢?

注意,
如果我们在设定动画初始值时使用的是ofFloat()函数,
则每个值的类型必定是Float类型,
我们获取到的类型也必然是Float类型。

同样,如果我们使用ofInt()函数设定动画初始值,
那么通过getAnimatedValue()函数获取到的值
就应该转换为Integer类型。


常用函数汇总
监听器
移除监听器
其他函数

至此,补充一个实战:
自定义View实战 | 弹跳的loading效果
一个主要是由ValueAnimator实现的自定义View








上一篇 下一篇

猜你喜欢

热点阅读