Android属性动画之ValueAnimator代码详解

属性动画通过改变一个对象的属性值来进行动画,属性动画包含了以下几个特性:

1、持续时间(Duration)

主要用来定义动画的持续时间,默认值为300ms。

2、时间插值器(Time interpolation)

指定时间变化的百分比,就是当前流逝时间除以指定的持续时间,这个可以自定义,继承Interpolator,重写getInterpolation方法。

3、重复次数和行为(Repeat count and behavior)

指定动画的执行次数和动画的重复模式

4、动画集(Animator sets)

可以把多个动画放到一个集合中,是他们同时执行,或者指定它们直接的顺序和延迟。

5、Frame refresh delay(帧刷新延迟)

可以指定如何去刷新动画的帧,默认是每10ms刷新一次,这个刷新也取决于系统的繁忙程度。

上面我们知道属性动画就是改变对象的属性值来实现动画,ValueAnimator的特点就是你不需要明确的指定你要改变的对象和属性,你只需要得到一个动态的值来自己去设置相应对象的属性,也就是它就是提供属性的变化值,你拿到这个值可以动态的更改对象属性值。总结一句就是监听动画过程,自己实现属性的改变。

举个例子:

// 这里指定了值的变化范围
ValueAnimator animator = ValueAnimator.ofFloat(0, 500);
// 这里指定变化持续时间
animator.setDuration(1000);
//开始动画
animator.start()
//开始动画后,我们可以动态的获取变化值
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
  @Override
  public void onAnimationUpdate(ValueAnimator animation)
  {
    //根据变化值来设置imageView对象的Y轴坐标,这样就实现了imageView的垂直移动
    imageView.setTranslationY((Float) animation.getAnimatedValue());
  }
});

上面使用imageView.setTranslationY((Float) animation.getAnimatedValue())来动态的改变图片的translationY属性,需要说明的是,如果在低版本中,我们使用的是NineOldAnimations这个库,用法跟系统基本一致,在NineOldAnimations里面我们动态改变对象的属性的时候,它提供了一个ViewHelper类,它是设置各种动画值的帮助类,可以简单的设置并应用动画值。所以在3.0以下版本中,使用ViewHelper来进行属性值的改变,上面的设置等同如下:

ViewHelper.setTranslationX(imageView, (Float) animation.getAnimatedValue());

上面的过程如下图所示:

上面的过程应该比较清晰,在上面我们就设置了一个持续时间,下面我们可以来看看我们可以为ValueAnimator设置其他哪些东西。

public ObjectAnimator setDuration(long duration)
设置持续时间

public void setEvaluator(TypeEvaluator value)
设置估值器

public void setInterpolator(/*Time*/Interpolator value)
设置插值器

public void setTarget(Object target)
设置目标对象

public void setRepeatCount(int value)
设置动画重复次数

public void setRepeatMode(int value)
设置重复模式

public void setValues(PropertyValuesHolder... values)
设置值

public void setStartDelay(long startDelay)
设置启动延时

public static void setFrameDelay(long frameDelay)
设置帧延迟

public void setIntValues(int... values)
设置Int值,对应ValueAnimator.ofInt函数

public void setFloatValues(float... values)
设置Float值。对应ValueAnimator.ofFloat函数

public void setCurrentPlayTime(long playTime)
设置当前执行时间

public void setObjectValues(Object... values)
设置Object值,对应ValueAnimator.ofObject函数

上面我们知道ValueAnimator是主要提供一个动态的变化值,这个值是怎么来变化的,它的变化函数就是由估值器和插值器来决定的,我们可以自定义估值器和插值器来自定义值的变化,另外这个变化值的类型,ValueAnimator提供了四种类型,Int,Float,Objcet,PropertyValuesHolder,它囊括了所有的类型。

1、变化值的类型的确定

我们知道,在我们定义一个属性动画对象的时候,可以不需要通过自己来创建的,主要有四种方式:

public static ValueAnimator ofInt(int... values) 

public static ValueAnimator ofFloat(int... values)

public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values) 

public static ValueAnimator ofPropertyValuesHolder(PropertyValuesHolder... values)

从上面我们可以看到,不同的方式其实对应的就是不同类型的变化值。第一种方式的变化值类型为Int,第二种方式的变化值类型为Float,第三种方式的变化值类型为Object,第四种方式的变化值类型为PropertyValuesHolder,它其实是一个集合。

2、估值器和插值器

对于给定一个范围的值,例如上面例子中ValueAnimator.ofFloat(0, 500),它给定的变化范围为[0, 500],那么在这个范围内到底是如何变化的呢?可以是线性变化,可以是加速变化,可以是减速变化,在内部已经为我们定义好了几种变化方式,我们可以根据情况来进行使用。

首先我们来说说时间插值器和类型估值器

TimeInterpolator中文翻译为时间插值器,它的作用是根据时间流逝的百分比来计算出当前属性值改变的百分比,系统预置的有LinearInterpolator(线性插值器:匀速动画)、AccelerateDecelerateInterpolator(加速减速插值器:动画两头慢中间快)和DecelerateInterpolator(减速插值器:动画越来越慢)等;

下面看看线性插值器的源码:

public class LinearInterpolator implements Interpolator {
	public LinearInterpolator() {
	}
	public LinearInterpolator(Context context, AttributeSet attrs) {
	}
	public float getInterpolation(float input) {
		return input;
	}
}

我们自定义插值器的时候,只需要重写getInterpolation方法,其中传入的input参数就是时间流逝的百分比,这个百分比就是当前时间的流逝除以设置的持续时间Duration来得到的。我们实现这个函数的时候,可以通过改变这个值来实现我们想要的效果。

TypeEvaluator的中文翻译为类型估值算法,它的作用是根据当前属性改变的百分比来计算改变后的属性值,系统预置的有IntEvaluator(针对整型属性)、FloatEvaluator(针对浮点型属性)和ArgbEvaluator(针对Color属性)。

我们知道插值器的作用就是返回当前属性改变的百分比,这个百分比我们可以通过重写getInterpolation来自定义。其实真正的变化后的值是从估值器来得到的。

我们来看看IntEvaluator的源码:

public class IntEvaluator implements TypeEvaluator<Integer> { 

  public Integer evaluate(float fraction, Integer startValue, Integer endValue) {
    int startInt = startValue;
    return (int)(startInt + fraction * (endValue - startInt));
  }
} 

上述算法很简单,evaluate的三个参数分别表示:估值小数、开始值和结束值,其中的估值小数就是上面getInterpolation的返回值,开始值就是变化值的开始,结束值就是变化值的结束,对应上面例子ValueAnimator.ofFloat(0, 500),开始值为0,结束值为500,通过这三个参数,最终计算出变化后的值,然后将这个值返回去,我们最终得到的就是这个值,然后对指定对象的属性进行设置,这样来实现指定属性值的变化,从而实现了动画效果。

所以我们如果希望自定义变化值的变化快慢,我们需要自定义一个插值器和一个估值器,插值器是为估值器服务的,估值器是为我们服务的,因为它最终返回了变化后的值。

最后,我们如何得到这个变化后的值呢?从上面的例子中我们可以看到,我们只需要使用ValueAnimator的addUpdateListener函数来增加一个更新监听,当这个值变化之后,就会回调onAnimationUpdate函数,在传入的参数ValueAnimator对象中使用getAnimatedValue函数我们就可以获取到变化后的那个值,拿到这个变化后的值之后我们就可以动态的更新对象的属性值了。

还有需要注意的是,我们如果没有显式指定插值器和估值器,它内部有默认值。

下面我们来举个例子;

/**
 * 抛物线
 * @param view
 */
public void paowuxian(View view)
{ 

  ValueAnimator valueAnimator = new ValueAnimator();
  valueAnimator.setDuration(3000);
  //这个地方设置了变化值的类型
  valueAnimator.setObjectValues(new PointF(0, 0));
  //设置插值器
  valueAnimator.setInterpolator(new LinearInterpolator());
  //设置估值器
  valueAnimator.setEvaluator(new TypeEvaluator<PointF>()
  {
    // fraction = t / duration
    @Override
    public PointF evaluate(float fraction, PointF startValue,
        PointF endValue)
    {
      Log.e(TAG, fraction * 3 + "");
      // x方向200px/s ,则y方向0.5 * 10 * t
      PointF point = new PointF();
      point.x = 200 * fraction * 3;
      point.y = 0.5f * 200 * (fraction * 3) * (fraction * 3);
      //返回变化值
      //这个返回值会在addUpdateListener的回调中得到
      return point;
    }
  }); 

  valueAnimator.start();
  valueAnimator.addUpdateListener(new AnimatorUpdateListener()
  {
    @Override
    public void onAnimationUpdate(ValueAnimator animation)
    {
      // 得到估值器里面的那个返回值
      PointF point = (PointF) animation.getAnimatedValue();
      //设置属性值
      mBlueBall.setX(point.x);
      mBlueBall.setY(point.y); 

    }
  });
} 

上面基本说清楚了ValueAnimator的特定和用法,下面来说说如何为这个动画添加事件监听。

ValueAnimator animator = ValueAnimator.ofFloat();
animator.setFloatValues(0, 500);
animator.setTarget(imageView);
animator.setDuration(1000);
animator.start();
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener()
{
  @Override
  public void onAnimationUpdate(ValueAnimator animation)
  {
    imageView.setTranslationY((Float) animation.getAnimatedValue());
  }
});

animator.addListener(new Animator.AnimatorListener(){

  @Override
  public void onAnimationStart(Animator animation) {
    Log.d(TAG, "onAnimationStart");
  }

  @Override
  public void onAnimationEnd(Animator animation) {
    Log.d(TAG, "onAnimationEnd");
  }

  @Override
  public void onAnimationCancel(Animator animation) {
    Log.d(TAG, "onAnimationCancel");
  }

  @Override
  public void onAnimationRepeat(Animator animation) {
    Log.d(TAG, "onAnimationRepeat");
  }
});

从上面可以看到直接添加一个监听就可以了,这样就可以监听动画的开始、结束、被取消、重复等事件,上面你需要重写上面四个函数一个都不能少,如果你只需要重写自己需要的函数,那你可以使用AnimatorListenerAdapter,例如只需要重新onAnimationEnd函数,因为AnimatorListenerAdapter继承自AnimatorListener

总结

以上本文关于Android属性动画之ValueAnimator代码详解的全部内容,希望对大家有所帮助。感兴趣的朋友可以继续参阅本站其他相关专题,如有不足之处,欢迎留言指出。感谢朋友们对本站的支持!

(0)

相关推荐

  • 图文详解Android属性动画

    Android中的动画分为视图动画(View Animation).属性动画(Property Animation)以及Drawable动画.从Android 3.0(API Level 11)开始,Android开始支持属性动画,本文主要讲解如何使用属性动画.关于视图动画可以参见博文<Android四大视图动画图文详解>. 一.概述 视图动画局限比较大,如下所述: 1.视图动画只能使用在View上面. 2.视图动画并没有真正改变View相应的属性值,这导致了UI效果与实际View状态存在差异

  • Android源码解析之属性动画详解

    前言 大家在日常开发中离不开动画,属性动画更为强大,我们不仅要知道如何使用,更要知道他的原理.这样,才能得心应手.那么,今天,就从最简单的来说,了解下属性动画的原理. ObjectAnimator .ofInt(mView,"width",100,500) .setDuration(1000) .start(); ObjectAnimator#ofInt 以这个为例,代码如下. public static ObjectAnimator ofInt(Object target, Stri

  • Android属性动画特点详解

    本文实例为大家分享了Android属性动画使用的具体代码,供大家参考,具体内容如下 MainActivity.java /* 属性动画的特点:动画效果会改变控件的位置.且开启动画的是动画对象,而不是控件对象. 只有旋转的属性动画是经常用的,注意参数. 注意:这些方法都是安卓在3.0以后出现的新特性,所以要把AndroidManifest.xml里的android:minSdkVersion值修改为11以上 */ //注释后面有222的暂时不用管. public class MainActivit

  • Android属性动画实现布局的下拉展开效果

    在Android的3.0之后,google又提出了属性动画的这样一个框架,他可以更好的帮助我们实现更丰富的动画效果.所以为了跟上技术的步伐,今天就聊一聊属性动画. 这一次的需求是这样的:当点击一个View的时候,显示下面隐藏的一个View,要实现这个功能,需要将V iew的visibility属性设置gone为visible即可,但是这个过程是一瞬间的,并不能实现我们要的效果.所以,属性动画是个不错的方案. 先把效果贴上 第一个:  第二个: 前面的这个是隐藏着,后面这个是显示的.当点击这个箭头

  • Android 属性动画ValueAnimator与插值器详解

    Android 属性动画ValueAnimator与插值器详解 一.ValueAnimator详解: ValueAnimator是整个动画的核心,ObjectAnimator即是继承自ValueAnimator来实现. ValueAnimator更像是一个数值发生器,用来产生具有一定规律的数字,从而让调动者来控制动画的实现过程. 1.ValueAnimator的使用: ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 100); val

  • Android 属性动画原理与DataBinding

    Android 属性动画原理与DataBinding 看到这个标题的时候你可能会有疑问,属性动画和 DataBinding 之间有什么关系?我个人理解的是:它们内部的实现思想有相似之处.这篇文章主要对 Android 属性动画的知识通过文字进行整理记录,内容参考于<Android开发艺术探索>,在最后会给出我如此理解属性动画和 DataBinding 的原因. Android动画概述: Android 的动画可以分为三种:View 动画.帧动画和属性动画,View 动画通过对场景里的对象不断做

  • android 帧动画,补间动画,属性动画的简单总结

    帧动画--FrameAnimation 将一系列图片有序播放,形成动画的效果.其本质是一个Drawable,是一系列图片的集合,本身可以当做一个图片一样使用 在Drawable文件夹下,创建animation-list为根节点的资源文件 <animation-list android:oneshot="false"> <item android:drawable="@drawable/img1" android:duration="100

  • Android使用属性动画如何自定义倒计时控件详解

    为什么要引入属性动画? Android之前的补间动画机制其实还算是比较健全的,在android.view.animation包下面有好多的类可以供我们操作,来完成一系列的动画效果,比如说对View进行移动.缩放.旋转和淡入淡出,并且我们还可以借助AnimationSet来将这些动画效果组合起来使用,除此之外还可以通过配置Interpolator来控制动画的播放速度等等等等.那么这里大家可能要产生疑问了,既然之前的动画机制已经这么健全了,为什么还要引入属性动画呢? 其实上面所谓的健全都是相对的,如

  • Android帧动画、补间动画、属性动画用法详解

    在安卓开发中,经常会使用到一些动画,那么在开发中,如何使用这些动画呢? 帧动画:不是针对View做出一些形状上的变化,而是用于播放一张张的图片,例如一些开机动画,类似于电影播放,使用的是AnimationDrawable来播放帧动画 res/drawable <?xml version="1.0" encoding="utf-8"?> <animation-list xmlns:android="http://schemas.androi

  • Android属性动画实现炫酷的登录界面

    我们聊聊我们常写的登录界面,这个界面我相信很多人都写过,而且也没什么难度,但是如果要实现比较不一般的效果,那就要花点心思了,先看看项目的效果吧: 我一直都不知道怎么在编辑框连设置图片大小,所以这个图不怎么样适配编辑框了,大家先凑合着看看. 我先讲讲思路,当我们输入完账号跟密码之后,点击登录,那这个输入框就慢慢的消失,在消失后,紧接着就出现这个进度的界面. 思路有了,那我们就开始编码了: 新建一个项目,然后系统生成了一个MainActivity.java文件和activity_main.xml文件

随机推荐