一、ofObject()概述

前面我们讲了ofInt()和ofFloat()来定义动画,但ofInt()只能传入Integer类型的值,而ofFloat()则只能传入Float类型的值。那如果我们需要操作其它类型的变量要怎么办呢?其实ValueAnimator还有一个函数ofObject(),可以传进去任何类型的变量,定义如下:

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

它有两个参数,第一个是自定义的Evaluator,第二个是可变长参数,Object类型的; 
大家可能会疑问,为什么要强制传进去自定义的Evaluator?首先,大家知道Evaluator的作用是根据当前动画的显示进度,计算出当前进度下把对应的值。那既然Object对象是我们自定的,那必然从进度到值的转换过程也必须由我们来做,不然系统哪知道你要转成个什么鬼。 
好了,现在我们先简单看一下ofObject这个怎么用。 
我们先来看看我们要实现的效果:

从效果图中可以看到,按钮上的字母从A变化到Z,刚开始变的慢,后来逐渐加速;

ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
char text = (char)animation.getAnimatedValue();
tv.setText(String.valueOf(text));
}
});
animator.setDuration(10000);
animator.setInterpolator(new AccelerateInterpolator());
animator.start();

这里注意三点: 
第一,构造时:

ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));  

我们自定义的一个CharEvaluator,这个类实现,后面会讲;在初始化动画时,传进去的是Character对象,一个是字母A,一个是字母Z; 
我们这里要实现的效果是,对Character对象来做动画,利用动画自动从字母A变到字母Z,具体怎么实现就是CharEvaluator的事了,这里我们只需要知道,在构造时传进去的是两个Character对象

第二:看监听:

char text = (char)animation.getAnimatedValue();
tv.setText(String.valueOf(text));

通过animation.getAnimatedValue()得到当前动画的字符,然后把字符设置给textview;大家知道我们构造时传进去的值类型是Character对象,所以在动画过程中通过Evaluator返回的值类型必然跟构造时的类型是一致的,也是Character

第三:插值器

animator.setInterpolator(new AccelerateInterpolator()); 

我们使用的是加速插值器,加速插值器的特点就是随着动画的进行,速度会越来越快,这点跟我们上面的效果图是一致的。 
下面最关键的就是看CharEvaluator是怎么实现的了,先抛开的代码,我们先讲一个点,ASCII码中数值与字符的转换方法。 
我们知道在ASCII码表中,每个字符都是有数字跟他一一对应的,字母A到字母Z之间的所有字母对应的数字区间为65到90; 
而且在程序中,我们能通过数字强转成对应的字符。 
比如:

数字转字符:

char  temp = (char)65;//得到的temp的值就是大写字母A  

字符转数字:

char temp = 'A';
int num = (int)temp;

在这里得到的num值就是对应的ASCII码值65; 
好了,在我们理解了ASCII码数值与对应字符的转换原理之后,再来看看CharEvaluator的实现:

public class CharEvaluator implements TypeEvaluator<Character> {
@Override
public Character evaluate(float fraction, Character startValue, Character endValue) {
int startInt = (int)startValue;
int endInt = (int)endValue;
int curInt = (int)(startInt + fraction *(endInt - startInt));
char result = (char)curInt;
return result;
}
}

在这里,我们就利用A-Z字符在ASCII码表中对应数字是连续且递增的原理,先求出来对应字符的数字值,然后再转换成对应的字符。代码难度不大,就不再细讲了。 
好了,到这里,有关ofObject()的使用大家应该就会了,上面我们说过,ofObject()能够初始化任何对象,下面我们就稍微加深些难度, 我们自定义一个类对象,然后利用ofObject()来构造这个对象的动画。

二、ofObject之自定义对象示例

我们先看看这部分,我们将实现的效果:

在这里,我们自定义了一个View,在这个view上画一个圆,但这个圆是有动画效果的。从效果中可以看出使用的插值器应该是回弹插值器(BounceInterpolator) 
下面就来看看这个动画是怎么做出来的

1、首先,我们自定义一个类Point:

public class Point {
private int radius; public Point(int radius){
this.radius = radius;
} public int getRadius() {
return radius;
} public void setRadius(int radius) {
this.radius = radius;
}
}

point类内容很简单,只有一个成员变量:radius表示当前point的半径。

2、然后我们自定义一个View:MyPointView

public class MyPointView extends View {
private Point mCurPoint;
public MyPointView(Context context, AttributeSet attrs) {
super(context, attrs);
} @Override
protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mCurPoint != null){
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(300,300,mCurPoint.getRadius(),paint);
}
} public void doPointAnim(){
ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(),new Point(20),new Point(200));
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurPoint = (Point)animation.getAnimatedValue();
invalidate();
}
});
animator.setDuration(1000);
animator.setInterpolator(new BounceInterpolator());
animator.start();
}
}

(1)、doPointAnim()函数

在这段代码中,首先来看看供外部调用开始动画的doPointAnim()函数:

public void doPointAnim(){
ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(),new Point(20),new Point(200));
animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurPoint = (Point)animation.getAnimatedValue();
invalidate();
}
});
animator.setDuration(1000);
animator.setInterpolator(new BounceInterpolator());
animator.start();
}

同样,先来看ofObject的构造动画的方法:

ValueAnimator animator = ValueAnimator.ofObject(new PointEvaluator(),new Point(20),new Point(200));  

在构造动画时,动画所对应的值的类型是Point对象,那说明我们自定义的PointEvaluator中的返回值也必然是Point了。有关PointEvaluator的实现后面再讲 
然后再来看看动画过程监听:

animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
mCurPoint = (Point)animation.getAnimatedValue();
invalidate();
}
});

在监听过程中,先根据animation.getAnimatedValue()得到当前动画进度所对应的Point实例,保存在mCurPoint中,然后强制刷新

(2)、OnDraw()函数

在强制刷新之后,就会走到OnDraw()函数下面:

protected void onDraw(Canvas canvas) {
super.onDraw(canvas);
if (mCurPoint != null){
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.RED);
paint.setStyle(Paint.Style.FILL);
canvas.drawCircle(300,300,mCurPoint.getRadius(),paint);
}
}

onDraw函数没什么难度,就是根据mCurPoint的半径在(300,300)的位置画出来圆形,有关绘图的知识大家可以参考另一个系列《android Graphics(一):概述及基本几何图形绘制》

(3)、PointEvaluator

在构造ofObject中,我们也可以知道,初始值和动画中间值的类型都是Point类型,所以PointEvaluator输入的返回类型都应该是Point类型的,先看看PointEvaluator的完整代码:

public class PointEvaluator implements TypeEvaluator<Point> {
@Override
public Point evaluate(float fraction, Point startValue, Point endValue) {
int start = startValue.getRadius();
int end = endValue.getRadius();
int curValue = (int)(start + fraction * (end - start));
return new Point(curValue);
}
}

这段代码其实比较容易理解,就是根据初始半径和最终半径求出当前动画进程所对应的半径值,然后新建一个Point对象返回。

3、使用MyPointView

首先在main.xml中添加对应的控件布局:从效果图中也可以看到,我们将MyPointView是布局在最下方的,布局代码如下:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"> <Button
android:id="@+id/btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentLeft="true"
android:padding="10dp"
android:text="start anim"
/> <Button
android:id="@+id/btn_cancel"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignParentRight="true"
android:padding="10dp"
android:text="cancel anim"
/>
<TextView
android:id="@+id/tv"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_centerHorizontal="true"
android:gravity="center"
android:padding="10dp"
android:background="#ffff00"
android:text="Hello qijian"/> <com.harvic.BlogValueAnimator4.MyPointView
android:id="@+id/pointview"
android:layout_below="@id/tv"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>

其实也没什么难度,就是在原来的布局代码下面加一个MyPointView控件,难度不大,不再细讲了 
然后我们来看看在MyActivity.java中是怎么来用的吧

public class MyActivity extends Activity {
private Button btnStart;
private MyPointView mPointView; @Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main); btnStart = (Button) findViewById(R.id.btn);
mPointView = (MyPointView)findViewById(R.id.pointview); btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mPointView.doPointAnim();
}
});
}
}

这段代码没什么难度,就是在点击start anim按钮的时候,调用mPointView.doPointAnim()方法开始动画。

本文转自:自定义控件三部曲之动画篇(六)——ValueAnimator高级进阶(二)

android.animation(3) - ValueAnimator-ofObject(TypeEvaluator evaluator, Object... values)的更多相关文章

  1. android.animation(2) - ValueAnimator的 Interpolator 和 Evaluator

    一.插值器 插值器,也叫加速器:有关插值器的知识,我在<Animation动画详解(二)——Interpolator插值器>中专门讲过,大家可以先看看这篇文章中各个加速器的效果.这里再讲一 ...

  2. android.animation(1) - ValueAnimator的ofInt(), ofFloat(), addUpdateListener(), addListener()(转)

    一.概述 long long ago,我写过几篇有关Animation的文章,讲解了传统的alpha.scale.translate.rotate的用法及代码生成方法.其实这三篇文章讲的所有动画效果叫 ...

  3. Android Animation(动画)

    前言 Android 平台提供实现动画的解决方案(三种) 一.3.0以前,android支持两种动画: (1)Frame Animation:顺序播放事先做好的图像,与gif图片原理类似,是一种逐帧动 ...

  4. android.animation(5) - PropertyValuesHolder与Keyframe(转)

    前几篇给大家讲了ValueAnimator.ObjectAnimator的知识,讲解了它们ofInt(),ofFloat(),ofObject()函数的用法.细心的同学可能会注意到,ValueAnim ...

  5. android.animation(4) - ObjectAnimator的ofInt(), ofFloat()(转)

    一.概述 1.引入 上几篇给大家讲了ValueAnimator,但ValueAnimator有个缺点,就是只能对数值对动画计算.我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作.这样使用起 ...

  6. Android动画学习笔记-Android Animation

    Android动画学习笔记-Android Animation   3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中 ...

  7. Android Animation初识

    3.0以前,android支持两种动画模式,tween animation,frame animation,在android3.0中又引入了一个新的动画系统:property animation,这三 ...

  8. Android Animation简述

    Android Animation简述 一.动画(Animation)          Android框架提供了两种动画系统:属性动画(Android3.0)和视图动画.同时使用两种动画是可行的,但 ...

  9. Android - Animation(二)

    Android - Animation(一) 一文总结了Android中的补间动画(View Animation/Tween Animation)和帧动画(Drawable Animation/Fra ...

随机推荐

  1. [转] Markdown

    转自 https://en.wikipedia.org/wiki/Markdown#Example 英文版本 - http://daringfireball.net/projects/markdown ...

  2. linux系统安装gcc

    安装nginx时会遇到错误提示gcc: command not found,需要先安装gcc 在centos7上安装成功. # yum group list # yum group install & ...

  3. go语言基础之函数类型

    1.函数类型 示例: package main import "fmt" func Add(a, b int) int { return a + b } func main() { ...

  4. C#连接SQL Server数据库进行简单操作[转]

    环境:VS2010 + SqlServer 2008 首先,按照面向对象的程序设计思想,设计一个数据库操作工具类MyTool.cs,该类中封装了关于数据库连接和操作的方法,各个功能模块在需进行数据库操 ...

  5. log4net 使用笔记

    一.Log4net特征 1.自定义日志输出级别 Log4net将日志分为五个级别优先级从高到低依次:FATAL > ERROR > WARN > INFO > DEBUG,此外 ...

  6. IOS中的XML解析之DOM和SAX

    一.介绍 dom是w3c指定的一套规范标准,核心是按树形结构处理数据,dom解析器读入xml文件并在内存中建立一个结构一模一样的“树”,这树各节点和xml各标记对应,通过操纵此“树”来处理xml中的文 ...

  7. mongodb pymongo.errors.CursorNotFound: Cursor not found, cursor id: 82792803897

    默认 mongo server维护连接的时间窗口是十分钟 默认 单次从 server获取数据是101条或者 大于1M小于16M的数据 所以默认情况下,如果10分钟内未能处理完数据,则抛出该异常. 解决 ...

  8. [Angular-Scaled web] 4. Using ui-router's named views

    In the previous post, we use $stateProvider deriect to root url and using MainCtrl, categories.tmpl. ...

  9. 推荐大家一个CSS书写规范

    CSS书写顺序 1.位置属性(position, top, right, z-index, display, float等) 2.大小(width, height, padding, margin) ...

  10. Android studio DrawerLayout

    网上开源项目地址:https://github.com/ikimuhendis/LDrawer 效果图: watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvQW ...