Android 动画 ObjectAnimator基本使用
2016-02-14 11:28
741 查看
一.概述
之前讲了ValueAnimator,但是有个缺点,就是只能对数值对动画进行计算,我们要想对哪个控件操作,需要监听动画过程,在监听中对控件操作。这样使用起来相比补间动画而言就相对比较麻烦。为了能让动画直接与对应控件相关联,以使我们从监听动画过程中解放出来,谷歌的开发人员在ValueAnimator的基础上,又派生了一个类ObjectAnimator。
由于ObjectAnimator是派生自ValueAnimator的,所以ValueAnimator中所能使用的方法,在ObjectAnimator中都可以正常使用。
但是ObjectAnimator也重写了几个方法,比如ofInt(),ofFloat(),我们先看看用ObjectAnimator的ofFloat如何实现一个动画。
1.使用
[code]public class MainActivity extends ActionBarActivity { private TextView textView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); textView = (TextView) findViewById(R.id.textview); } public void start(View view){ ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "alpha", 1,0,1); animator.setDuration(2000); animator.start(); } }
效果如下
我们这里使用的构造方法为
[code] public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
第一个参数为添加动画的对象
第二个参数为动画属性名称,这里我们使用alpha透明度动画
第三个参数为要改变的值,是可变的,这里我们从1变为0再变为1,也就是从不透明变成透明,然后变回来。
下面我们在看看如何实现旋转效果
[code]public void start(View view){ ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,0); animator.setDuration(2000); animator.start(); }
效果如下:
从代码中可以看到,我们只需要改变ofFloat()的第二个参数的值就可以实现对应的动画。
那么问题来了,我们怎么知道第二个参数的值是啥呢?
2.set函数
我们在会看构造ObjectAnimator时的构造方法
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,0);
TextView有rotation这个属性吗,没有,连View中也没有,那它是怎么改变这个值的?其实,ObjectAnimator做动画,并不是根据控件xml中的属性来改变的,而是通过指定属性所对应的set方法来改变的。比如,我们上面指定的改变rotation的属性值,ObjectAnimator在做动画时就会到指定控件(TextView)中去找对应的setRotation()方法来改变控件中对应的值。同样的道理,当我们在最开始的示例代码中,指定改变”alpha”属性值的时候,ObjectAnimator也会到TextView中去找对应的setAlpha()方法。那TextView中都有这些方法吗,有的,这些方法都是从View中继承过来的,在View中有关动画,总共有下面几组set方法:
[code]//1、透明度:alpha public void setAlpha(float alpha) //2、旋转度数:rotation、rotationX、rotationY public void setRotation(float rotation) public void setRotationX(float rotationX) public void setRotationY(float rotationY) //3、平移:translationX、translationY public void setTranslationX(float translationX) public void setTranslationY(float translationY) //缩放:scaleX、scaleY public void setScaleX(float scaleX) public void setScaleY(float scaleY)
可以看到在View中已经实现了有关alpha,rotaion,translate,scale相关的set方法。所以我们在构造ObjectAnimator时可以直接使用。
1、要使用ObjectAnimator来构造对画,要操作的控件中,必须存在对应的属性的set方法
2、setter 方法的命名必须以骆驼拼写法命名,即set后每个单词首字母大写,其余字母小写,即类似于setPropertyName所对应的属性为propertyName
下面我们就来看一下上面中各个方法的使用方法及作用。
(1)setRotation,setRotationX,setRotationY
setRotation:绕z轴转
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotation", 0,180,360); animator.setDuration(2000); animator.start();
setRotationX:绕X轴转
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotationX", 0,180,360); animator.setDuration(2000); animator.start();
setRotationY:绕Y轴转
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "rotationY", 0,180,360); animator.setDuration(2000); animator.start();
(2) setTranslationX,setTranslationY
setTranslationX(float translationX):X方向移动的距离,以当前控件为原点,向右为正方向,参数translationX表示移动的距离。
setTranslationY(float translationY):
Y方向移动的距离,以当前控件为原点,向右为正方向,参数translationY表示移动的距离。
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationX", 0,200,-200,0); animator.setDuration(2000); animator.start();
[code] ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "translationY", 0,200,-200,0); animator.setDuration(2000); animator.start();
(3)setScaleX(float scaleX) :在X轴上缩放,scaleX表示缩放倍数
setScaleY(float scaleY) ::在Y轴上缩放,scaleY表示缩放倍数
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "scaleX", 0,3,2,0); animator.setDuration(2000); animator.start();
我们可以看到,TextView在X方向从0倍变为3倍,然后变为2倍,最后又变为0倍,也就是消失了。
[code]ObjectAnimator animator = ObjectAnimator.ofFloat(textView, "scaleY", 0,3,2,0); animator.setDuration(2000); animator.start();
二.原理
可以看到ObjectAnimator的动画流程中,也是首先通过加速器产生当前进度的百分比,然后再经过Evaluator生成对应百分比所对应的数字值。这两步与ValueAnimator是完全一样的,唯一不同的是最后一步,在ValueAnimator中,我们要通过添加监听器来监听当前数字值。而在ObjectAnimator中,则是先根据属性值拼装成对应的set函数的名字,比如这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到对应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(float scale)的参数将其传入。
这里在找到控件的set函数以后,是通过反射来调用这个函数的,
好了,在知道了ObjectAnimator的原理以后,下面就来看看如何自定义一个ObjectAnimator的属性吧。
三.自定义ObjectAnimator属性
我们自定义一个圆形,然后将它的半径从0变为3倍然后变为1倍,下面看看怎么实现
1.保存圆信息的Point类
[code]public class Point { private float radius; public Point(float radius) { this.radius = radius; } public void setRadius(float radius) { this.radius = radius; } public float getRadius() { return radius; } }
只有一个属性,就是半径
2.自定义的View,画一个圆形
[code] public class MyPointView extends View{ //创建圆形对象,半径为100 private Point point = new Point(100); public MyPointView(Context context) { super(context); } public MyPointView(Context context, AttributeSet attrs) { super(context, attrs); } @Override protected void onDraw(Canvas canvas) { Paint paint = new Paint(); paint.setColor(Color.RED); paint.setAntiAlias(true); paint.setStyle(Style.FILL); //以300,300为圆心,以当前圆的半径为半径,画一个圆 canvas.drawCircle(300,300, point.getRadius(), paint); super.onDraw(canvas); } public void setPointRadius(float radius){ point.setRadius(radius); invalidate(); } }
我们来看看这个setPointRadius方法:
第一点:这个方法对应的属性是pointRadius或者PointRadius,第一个字母大小写不是强制的,后面的字母必须与set函数一致
第二点:在setPointRadius中,先将当前动画传过来的值保存到mPoint中,做为当前圆形的半径。然后强制界面刷新
3.java代码,
[code]public class MainActivity extends ActionBarActivity { private MyPointView pointView; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pointView = (MyPointView) findViewById(R.id.pointview); } public void start(View view){ ObjectAnimator animator = ObjectAnimator.ofFloat(pointView, "pointRadius", 0,300,100); animator.setDuration(2000); animator.start(); } }
我们可以看到,我们使用了pointRadius这个属性,对应的就是MyPointView类中的方法setPointRadius,点击按钮后,启动动画,ObjectAnimator就实时的把参数的值传递给setPointRadius这个函数,由于我们在这个函数中将半径设置给了圆形,然后重新绘制界面,所以可以看到圆的半径在不断变化。
3.何时需要实现对应属性的get函数
我们之前看到的ObjectAnimator的构造函数的第三个参数都是可变的,
[code] public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
那么我们如果传入一个参数会怎么样
[code] ObjectAnimator animator = ObjectAnimator.ofFloat(pointView, "pointRadius", 100); animator.setDuration(2000); animator.start();
我们可以看到,半径从0变为100,说明是从0开始变得,但是此时控制台已经给出了警告
为什么呢,因为当我们只设置一个值的时候,系统会调用get对应的属性值,如果找不到,就会使用默认的值开始动画,比如int类型为0,此时就会报出一个警告,如果给控件设置了get函数,就会从get函数对应的值开始动画。
[code]public float getPointRadius(){ return 50; }
我们可以看到,圆的半径是从50开始的,而不是0.
最后我们总结一下:当且仅当动画的只有一个过渡值时,系统才会调用对应属性的get函数来得到动画的初始值。
最后我们看看如何使用使用ArgbEvaluator
我们知道TextView有个属性可以改变背景颜色
[code]public void setBackgroundColor(int color)
大家可以回想到,我们在ValueAnimator中也曾改变过背景色,使用的是ArgbEvaluator。在这里我们再回顾下ArgbEvaluator,它的实现代码如下:
[code]public class ArgbEvaluator implements TypeEvaluator { public Object evaluate(float fraction, Object startValue, Object endValue) { int startInt = (Integer) startValue; int startA = (startInt >> 24); int startR = (startInt >> 16) & 0xff; int startG = (startInt >> 8) & 0xff; int startB = startInt & 0xff; int endInt = (Integer) endValue; int endA = (endInt >> 24); int endR = (endInt >> 16) & 0xff; int endG = (endInt >> 8) & 0xff; int endB = endInt & 0xff; return (int)((startA + (int)(fraction * (endA - startA))) << 24) | (int)((startR + (int)(fraction * (endR - startR))) << 16) | (int)((startG + (int)(fraction * (endG - startG))) << 8) | (int)((startB + (int)(fraction * (endB - startB)))); } }
这里主要说一下,ArgbEvaluator 返回值类型是int,所以我们要使用ofInt来实现动画
[code]ObjectAnimator animator = ObjectAnimator.ofInt(textview, "backgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff); animator.setDuration(2000); animator.setEvaluator(new ArgbEvaluator()); animator.start();
相关文章推荐
- Objective-C的NSOperation多线程类基本使用指南
- 面试----Object类
- iOS --- Objective-C 的switch语句中不能初始化对象
- object-assign
- Object Property 参数使用
- QT的Meta-Object系统
- Objective-C的知识小拓展
- Objective-C 和 C的对比
- 序列化 Activity之间进行数据传输 List<Object> Parcelable serializable两种方式
- The Java™ Tutorials — Concurrency :Thread Objects 线程对象
- Objective-C简介
- Attaching the Filter Device Object to the Target Device Object
- iOS开发--1【Objective-C】
- 【慕课笔记】U3 继承 第7节 JAVA中的Object类(二)
- 【慕课笔记】U3 继承 第6节 JAVA中的Object类(一)
- Scala 中object和class的区别
- NSGAIII中的normalization objectives
- (object sender, EventArgs e)中的sender 和e有什么用呀?
- Objective-C Runtime系统
- JS调试输出Object