前言:
假如生活欺骗了你,
不要悲伤,不要心急!

忧郁的日子里须要镇静:
相信吧,快乐的日子终将会来临!

心儿永远向往着未来;
如今却常是忧郁。
一切都是瞬息,一切都将会过去;
而那过去了的,就会成为亲切的怀恋。

—–普希金

相关文章:

《Android自己定义控件三部曲文章索引》http://blog.csdn.net/harvic880925/article/details/50995268

一、概述

1、引入

上几篇给大家讲了ValueAnimator。但ValueAnimator有个缺点。就是仅仅能对数值对动画计算。我们要想对哪个控件操作。须要监听动画过程,在监听中对控件操作。这样使用起来相比补间动画而言就相对照较麻烦。

为了能让动画直接与相应控件相关联,以使我们从监听动画过程中解放出来,谷歌的开发者在ValueAnimator的基础上,又派生了一个类ObjectAnimator;
因为ObjectAnimator是派生自ValueAnimator的。所以ValueAnimator中所能使用的方法,在ObjectAnimator中都能够正常使用。

但ObjectAnimator也重写了几个方法,比方ofInt(),ofFloat()等。我们先看看利用ObjectAnimator重写的ofFloat方法怎样实现一个动画:(改变透明度)

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"alpha",1,0,1);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:

我们这里还是直接使用上一篇的框架代码;(当点击start anim时运行动画)从上面的代码中能够看到构造ObjectAnimator的方法非常简单:

  1. public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
  • 第一个參数用于指定这个动画要操作的是哪个控件
  • 第二个參数用于指定这个动画要操作这个控件的哪个属性
  • 第三个參数是可变长參数。这个就跟ValueAnimator中的可变长參数的意义一样了。就是指这个属性值是从哪变到哪。像我们上面的代码中指定的就是将textview的alpha属性从0变到1再变到0;

以下我们再来看一下怎样实现旋转效果:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:

从代码中能够看到,我们仅仅须要改变ofFloat()的第二个參数的值就能够实现相应的动画;
那么问题来了,我们怎么知道第二个參数的值是啥呢?

2、setter函数

我们再回来看构造改变rotation值的ObjectAnimator的方法

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);

TextView控件有rotation这个属性吗?没有,不光TextView没有,连它的父类View中也没有这个属性。那它是怎么来改变这个值的呢?事实上,ObjectAnimator做动画,并非依据控件xml中的属性来改变的,而是通过指定属性所相应的set方法来改变的。比方,我们上面指定的改变rotation的属性值。ObjectAnimator在做动画时就会到指定控件(TextView)中去找相应的setRotation()方法来改变控件中相应的值。相同的道理,当我们在最開始的演示样例代码中,指定改变”alpha”属性值的时候,ObjectAnimator也会到TextView中去找相应的setAlpha()方法。那TextView中都有这些方法吗,有的。这些方法都是从View中继承过来的,在View中有关动画。总共同拥有以下几组set方法:

  1. //1、透明度:alpha
  2. public void setAlpha(float alpha)
  3.  
  4. //2、旋转度数:rotation、rotationX、rotationY
  5. public void setRotation(float rotation)
  6. public void setRotationX(float rotationX)
  7. public void setRotationY(float rotationY)
  8.  
  9. //3、平移:translationX、translationY
  10. public void setTranslationX(float translationX)
  11. public void setTranslationY(float translationY)
  12.  
  13. //缩放:scaleX、scaleY
  14. public void setScaleX(float scaleX)
  15. public void setScaleY(float scaleY)

能够看到在View中已经实现了有关alpha,rotaion,translate,scale相关的set方法。所以我们在构造ObjectAnimator时能够直接使用。
在開始逐个看这些函数的使用方法前。我们先做一个总结:
1、要使用ObjectAnimator来构造对画,要操作的控件中。必须存在相应的属性的set方法
2、setter 方法的命名必须以骆驼拼写法命名。即set后每一个单词首字母大写,其余字母小写,即相似于setPropertyName所相应的属性为propertyName
以下我们就来看一下上面中各个方法的使用方法及作用。
有关alpha的使用方法。上面已经讲过了,以下我们来看看其他的

(1)、setRotationX、setRotationY与setRotation

  • setRotationX(float rotationX):表示环绕X轴旋转,rotationX表示旋转度数
  • setRotationY(rotationY):表示环绕Y轴旋转,rotationY表示旋转度数
  • setRotation(float rotation):表示环绕Z旋转,rotation表示旋转度数

先来看看setRotationX的效果:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:


从效果图中明显看出,textview的旋转方法是环绕X轴旋转的,我们设定为从0度旋转到270度再返回0度。
然后再来看看setRotationY的使用方法与效果:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:


从效果图中明显能够看出环绕Y轴旋转的。
我们再来看看setRotation的使用方法与效果:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,270,0);
  2. animator.setDuration(2000);
  3. animator.start();


我们上面说了,setRotation是环绕Z轴旋转的,可能有些同学不理解什么是Z轴,我们来看一张图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

从这张图中,绿色框部分表示手机屏幕,非常明显能够看出Z轴就是从屏幕左上角原点向外伸出的一条轴。

这样。我们也就能够理解环绕Z轴旋转。为什么是这样子转了。

(2)、setTranslationX与setTranslationY

  • setTranslationX(float translationX) :表示在X轴上的平移距离,以当前控件为原点,向右为正方向。參数translationX表示移动的距离。
  • setTranslationY(float translationY) :表示在Y轴上的平移距离。以当前控件为原点。向下为正方向,參数translationY表示移动的距离。

我们先看看setTranslationX的使用方法:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200, -200,0);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:

所以。我们上面在构造动画时,指定的移动距离是(0, 200, -200,0)。所以控件会从自身全部位置向右移动200像素,然后再移动到距离原点-200的位置,最后回到原点。
然后我们来看看setTranslateY的使用方法:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200, -100,0);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:(为了方便看到效果。将textview垂直居中)

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

相同,移动位置的坐标也都是以当前控件所在位置为中心点的。所以相应的移动位置从原点移动向下移动200像素,然后再移动到向下到距原点200像素的位置,最后再回到(0,0)从效果图中非常明显能够看出来。

从上面能够看出:每次移动距离的计算都是以原点为中心的;比方初始动画为ObjectAnimator.ofFloat(tv, “translationY”, 0, 200, -100,0)表示首先从0移动到正方向200的位置,然后再移动到负方向100的位置。最后移动到原点。

(3)、setScaleX与setScaleY

  • setScaleX(float scaleX):在X轴上缩放。scaleX表示缩放倍数
  • setScaleY(float scaleY):在Y轴上缩放,scaleY表示缩放倍数

我们来看看setScaleX的使用方法:

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:

在效果图中,从0倍放大到3倍,然后再还原到1倍的原始状态。
然后再来看看setScaleY的使用方法

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
  2. animator.setDuration(2000);
  3. animator.start();

为了更好的看到效果,我把textview垂直居中了,效果图例如以下:

源代码在文章底部给出 

好了,到这里有关View中自带的set函数讲完了,我们来看看ObjectAnimator是怎样实现控件动画效果的。

3、ObjectAnimator动画原理

我们先来看张图:

在这张图中,将ValueAnimator的动画流程与ObjectAnimator的动画流程做了个对照。

能够看到ObjectAnimator的动画流程中,也是首先通过加速器产生当前进度的百分比。然后再经过Evaluator生成相应百分比所相应的数字值。这两步与ValueAnimator是全然一样的,唯一不同的是最后一步。在ValueAnimator中,我们要通过加入监听器来监听当前数字值。而在ObjectAnimator中,则是先依据属性值拼装成相应的set函数的名字,比方这里的scaleY的拼装方法就是将属性的第一个字母强制大写后,与set拼接,所以就是setScaleY。然后通过反射找到相应控件的setScaleY(float scaleY)函数,将当前数字值做为setScaleY(float scale)的參数将其传入。
这里在找到控件的set函数以后。是通过反射来调用这个函数的,有关反射的使用大家能够參考《夯实JAVA基本之二 —— 反射(1):基本类周边信息获取》
这就是ObjectAnimator的流程,最后一步总结起来就是调用相应属性的set方法。将动画当前数字值做为參数传进去。

依据上面的流程,这里有几个注意事项:
(1)、拼接set函数的方法:上面我们也说了是首先是强制将属性的第一个字母大写,然后与set拼接,就是相应的set函数的名字。

注意。仅仅是强制将属性的第一个字母大写,后面的部分是保持不变的。

反过来,假设我们的函数名命名为setScalePointX(float ),那我们在写属性时能够写成”scalePointX”或者写成“ScalePointX”都是能够的,即第一个字母大写和小写能够任意。但后面的部分必须与set方法后的大写和小写保持一致。
(2)、怎样确定函数的參数类型:上面我们知道了怎样找到相应的函数名,那相应的參数方法的參数类型怎样确定呢?我们在讲ValueAnimator的时候说过。动画过程中产生的数字值与构造时传入的值类型是一样的。因为ObjectAnimator与ValueAnimator在插值器和Evaluator这两步是全然一样的。而当前动画数值的产生是在Evaluator这一步产生的,所以ObjectAnimator的动画中产生的数值类型也是与构造时的类型一样的。那么问题来了,像我们的构造方法。

  1. ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);

因为构造时使用的是ofFloat函数,所以中间值的类型应该是Float类型的,所以在最后一步拼装出来的set函数应该是setScaleY(float xxx)的样式;这时,系统就会利用反射来找到setScaleY(float xxx)函数,并把当前的动画数值做为參数传进去。

那问题来了。假设没有相似setScaleY(float xxx)的函数,我们仅仅实现了一个setScaleY(int xxx)的函数怎么办?这里尽管函数名一样。但參数类型是不一样的。那么系统就会报一个错误:

意思就是相应函数的指定參数类型没有找到。
(3)、调用set函数以后怎么办?从ObjectAnimator的流程能够看到。ObjectAnimator仅仅负责把动画过程中的数值传到相应属性的set函数中就结束了。注意传给set函数以后就结束了。set函数就相当我们在ValueAnimator中加入的监听的作用,set函数中的对控件的操作还是须要我们自己来写的。

那我们来看看View中的setScaleY是怎么实现的吧:

  1. /**
  2. * Sets the amount that the view is scaled in Y around the pivot point, as a proportion of
  3. * the view's unscaled width. A value of 1 means that no scaling is applied.
  4. *
  5. * @param scaleY The scaling factor.
  6. * @see #getPivotX()
  7. * @see #getPivotY()
  8. *
  9. * @attr ref android.R.styleable#View_scaleY
  10. */
  11. public void setScaleY(float scaleY) {
  12. ensureTransformationInfo();
  13. final TransformationInfo info = mTransformationInfo;
  14. if (info.mScaleY != scaleY) {
  15. invalidateParentCaches();
  16. // Double-invalidation is necessary to capture view's old and new areas
  17. invalidate(false);
  18. info.mScaleY = scaleY;
  19. info.mMatrixDirty = true;
  20. mPrivateFlags |= DRAWN; // force another invalidation with the new orientation
  21. invalidate(false);
  22. }
  23. }

大家不必理解这一坨代码的意义,因为这些代码是须要读懂View的总体流程以后才干看得懂的。仅仅须要跟着我的步骤来理解即可。这段代码总共分为两部分:第一步又一次设置当前控件的參数,第二步调用Invalidate()强制重绘。
所以在重绘时,控件就会依据最新的控件參数来绘制了,所以我们就看到当前控件被缩放了。
(4)、set函数调用频率是多少:因为我们知道动画在进行时,每隔十几毫秒会刷新一次,所以我们的set函数也会每隔十几毫秒会被调用一次。
讲了这么多,就是为了强调一点:ObjectAnimator仅仅负责把当前运动动画的数值传给set函数。至于set函数里面怎么来做。是我们自己的事了。
好了,在知道了ObjectAnimator的原理以后,以下就来看看怎样自己定义一个ObjectAnimator的属性吧。

二、自己定义ObjectAnimator属性

上面我们已经看了使用View自带的set函数所相应属性的方法,并且理解了ObjectAnimator的动画实现原理,以下我们来自己定义一个属性来看看实现效果吧。
我们在開始之前再来捋一下ObjectAnimator的动画设置流程:ObjectAnimator须要指定操作的控件对象,在開始动画时,到控件类中去寻找设置属性所相应的set函数。然后把动画中间值做为參数传给这个set函数并运行它。
所以。我们说了,控件类中必须所要设置属性所要相应的set函数。所以为了自由控制控件的实现,我们这里自己定义一个控件。大家知道在这个自己定义控件中,肯定存在一个set函数与我们自己定义的属性相相应。
我们先来看看这段要实现的效果:

这个效果图与我们上篇自己定义控件实现的效果几乎相同,这个控件中存在一个圆形。也是在动画时先将这个圆形放大,然后再将圆形还原。

1、保存圆形信息类——Point

为了,保存圆形的信息,我们先定义一个类:(Point.java)

  1. public class Point {
  2. private int mRadius;
  3.  
  4. public Point(int radius){
  5. mRadius = radius;
  6. }
  7.  
  8. public int getRadius() {
  9. return mRadius;
  10. }
  11.  
  12. public void setRadius(int radius) {
  13. mRadius = radius;
  14. }
  15. }

这个类非常好理解,仅仅有一个成员变量mRadius,表示圆的半径。

2、自己定义控件——MyPointView

然后我们自己定义一个控件MyPointView,完整代码例如以下:

  1. public class MyPointView extends View {
  2. private Point mPoint = new Point(100);
  3.  
  4. public MyPointView(Context context, AttributeSet attrs) {
  5. super(context, attrs);
  6. }
  7.  
  8. @Override
  9. protected void onDraw(Canvas canvas) {
  10. if (mPoint != null){
  11. Paint paint = new Paint();
  12. paint.setAntiAlias(true);
  13. paint.setColor(Color.RED);
  14. paint.setStyle(Paint.Style.FILL);
  15. canvas.drawCircle(300,300,mPoint.getRadius(),paint);
  16. }
  17. super.onDraw(canvas);
  18. }
  19.  
  20. void setPointRadius(int radius){
  21. mPoint.setRadius(radius);
  22. invalidate();
  23. }
  24.  
  25. }

在这段代码中,首先来看我们前面讲到的set函数:

  1. void setPointRadius(int radius){
  2. mPoint.setRadius(radius);
  3. invalidate();
  4. }

第一点,这个set函数所相应的属性应该是pointRadius或者PointRadius。前面我们已经讲了第一个字母大写和小写无所谓,后面的字母必须保持与set函数全然一致。
第二点,在setPointRadius中,先将当前动画传过来的值保存到mPoint中。做为当前圆形的半径。

然后强制界面刷新
在界面刷新后。就開始运行onDraw()函数:

  1. @Override
  2. protected void onDraw(Canvas canvas) {
  3. if (mPoint != null){
  4. Paint paint = new Paint();
  5. paint.setAntiAlias(true);
  6. paint.setColor(Color.RED);
  7. paint.setStyle(Paint.Style.FILL);
  8. canvas.drawCircle(300,300,mPoint.getRadius(),paint);
  9. }
  10. super.onDraw(canvas);
  11. }

在onDraw函数中,就是依据当前mPoint的半径值在(300,300)点外画一个圆;有关画圆的知识。大家能够參考《android Graphics(一):概述及基本几何图形绘制》

3、使用MyPointView

首先,在MyActivity的布局中加入MyPointView的使用(main.xml):

  1. <?xml version="1.0" encoding="utf-8"?
  2.  
  3. >
  4. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
  5. android:orientation="vertical"
  6. android:layout_width="fill_parent"
  7. android:layout_height="fill_parent">
  8.  
  9. <Button
  10. android:id="@+id/btn"
  11. android:layout_width="wrap_content"
  12. android:layout_height="wrap_content"
  13. android:layout_alignParentLeft="true"
  14. android:padding="10dp"
  15. android:text="start anim"
  16. />
  17.  
  18. <Button
  19. android:id="@+id/btn_cancel"
  20. android:layout_width="wrap_content"
  21. android:layout_height="wrap_content"
  22. android:layout_alignParentRight="true"
  23. android:padding="10dp"
  24. android:text="cancel anim"
  25. />
  26. <TextView
  27. android:id="@+id/tv"
  28. android:layout_width="100dp"
  29. android:layout_height="wrap_content"
  30. android:layout_centerHorizontal="true"
  31. android:gravity="center"
  32. android:padding="10dp"
  33. android:background="#ffff00"
  34. android:text="Hello qijian"/>
  35.  
  36. <com.example.BlogObjectAnimator1.MyPointView
  37. android:id="@+id/pointview"
  38. android:layout_width="match_parent"
  39. android:layout_height="match_parent"
  40. android:layout_below="@id/tv"/>
  41.  
  42. </RelativeLayout>

布局代码非常好理解。依据效果图中的布局效果来理解。非常easy,就不再多讲
然后看看在MyActivity中,点击start anim后的处理方法:

  1. public class MyActivity extends Activity {
  2. private Button btnStart;
  3. private MyPointView mPointView;
  4.  
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. setContentView(R.layout.main);
  9.  
  10. btnStart = (Button) findViewById(R.id.btn);
  11. mPointView = (MyPointView)findViewById(R.id.pointview);
  12.  
  13. btnStart.setOnClickListener(new View.OnClickListener() {
  14. @Override
  15. public void onClick(View v) {
  16. doPointViewAnimation();
  17. }
  18. });
  19. }
  20. …………
  21. }

在点击start animbutton后。開始运行doPointViewAnimation()函数,doPointViewAnimation()函数代码例如以下:

  1. private void doPointViewAnimation(){
  2. ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius", 0, 300, 100);
  3. animator.setDuration(2000);
  4. animator.start();
  5. }

在这段代码中。着重看ObjectAnimator的构造方法,首先要操作的控件对象是mPointView,然后相应的属性是pointRadius,然后值是从0到300再到100;
所以在动画開始以后。ObjectAnimator就会实时地把动画中产生的值做为參数传给MyPointView类中的setPointRadius(int radius)函数,然后调用setPointRadius(int radius)。因为我们在setPointRadius(int radius)中实时地设置圆形的半径值然后强制重绘当前界面,所以能够看到圆形的半径会随着动画的进行而改变。

源代码在文章底部给出

四、注意——何时须要实现相应属性的get函数

我们再来看一下ObjectAinimator的以下三个构造方法:
  1. public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)
  2. public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
  3. public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)

前面我们已经分别讲过三个函数的使用方法,在上面的三个构造方法中最后一个參数都是可变长參数。我们也讲了,他们的意义就是从哪个值变到哪个值的。
那么问题来了:前面我们都是定义多个值,即至少两个值之间的变化,那假设我们仅仅定义一个值呢,如以下的方式:(相同以MyPointView为例)

  1. ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);

我们在这里仅仅传递了一个变化值100;那它从哪里開始变化呢?我们来看一下效果:
代码例如以下:

  1. ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);
  2. animator.setDuration(2000);
  3. animator.start();

效果图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

从效果图中看起来是从0開始的。可是看log能够看出来已经在出警告了:
我们点了三次start animbutton。所以这里也报了三次,意思就是没找到pointRadius属性所相应的getPointRadius()函数;
仅且仅当我们仅仅给动画设置一个值时,程序才会调用属性相应的get函数来得到动画初始值。假设动画没有初始值,那么就会使用系统默认值。比方ofInt()中使用的參数类型是int类型的,而系统的Int值的默认值是0,所以动画就会从0运动到100;也就是系统尽管在找到不到属性相应的get函数时,会给出警告,但同一时候会用系统默认值做为动画初始值。

假设通过给自己定义控件MyPointView设置了get函数,那么将会以get函数的返回值做为初始值:

  1. public class MyPointView extends View {
  2. private Point mPoint = new Point(100);
  3.  
  4. public MyPointView(Context context, AttributeSet attrs) {
  5. super(context, attrs);
  6. }
  7.  
  8. @Override
  9. protected void onDraw(Canvas canvas) {
  10. if (mPoint != null){
  11. Paint paint = new Paint();
  12. paint.setAntiAlias(true);
  13. paint.setColor(Color.RED);
  14. paint.setStyle(Paint.Style.FILL);
  15. canvas.drawCircle(300,300,mPoint.getRadius(),paint);
  16. }
  17. super.onDraw(canvas);
  18. }
  19.  
  20. public int getPointRadius(){
  21. return 50;
  22. }
  23.  
  24. public void setPointRadius(int radius){
  25. mPoint.setRadius(radius);
  26. invalidate();
  27. }
  28.  
  29. }

我们在这里加入了getPointRadius函数,返回值是Int.有些同学可能会疑惑:我怎么知道这里要返回int值呢?
我们前面说过当且仅当我们在创建ObjectAnimator时,仅仅给他传递了一个过渡值的时候,系统才会调用属性相应的get函数来得到动画的初始值!所以做为动画的初始值,那么在创建动画时过渡值传的什么类型,这里的get函数就要返回类型

  1. public static ObjectAnimator ofObject(Object target, String propertyName,TypeEvaluator evaluator, Object... values)

比方上面的ofObject,get函数所返回的类型就是与最后一个參数Object... values,相同类型的。

在我们在MyPointView加入上PointRadius所相应的get函数以后又一次运行动画:

  1. ObjectAnimator animator = ObjectAnimator.ofInt(mPointView, "pointRadius",100);
  2. animator.setDuration(2000);
  3. animator.start();

此时的效果图例如以下:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

从动画中能够看出。半径已经不是从0開始的了,而是从50開始的。
最后我们总结一下:当且仅当动画的仅仅有一个过渡值时,系统才会调用相应属性的get函数来得到动画的初始值。
源代码在文章底部给出

三、经常使用函数

有关经常使用函数这一节事实上没有太多讲的必要。

因为ObjectAnimator的函数都是从ValueAnimator中继承而来的。所以使用方法和效果与ValueAnimator是全然一样的。我们这里仅仅解说一下Evaluator的使用方法,其他的也就不再讲了。

1、使用ArgbEvaluator

我们搜一下TextView全部的函数发现,TextView有一个set函数能够改变背景色:

  1. public void setBackgroundColor(int color);

大家能够回想到,我们在ValueAnimator中也曾改变过背景色,使用的是ArgbEvaluator。在这里我们再回想下ArgbEvaluator,它的实现代码例如以下:

  1. public class ArgbEvaluator implements TypeEvaluator {
  2. public Object evaluate(float fraction, Object startValue, Object endValue) {
  3. int startInt = (Integer) startValue;
  4. int startA = (startInt >> 24);
  5. int startR = (startInt >> 16) & 0xff;
  6. int startG = (startInt >> 8) & 0xff;
  7. int startB = startInt & 0xff;
  8.  
  9. int endInt = (Integer) endValue;
  10. int endA = (endInt >> 24);
  11. int endR = (endInt >> 16) & 0xff;
  12. int endG = (endInt >> 8) & 0xff;
  13. int endB = endInt & 0xff;
  14.  
  15. return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
  16. (int)((startR + (int)(fraction * (endR - startR))) << 16) |
  17. (int)((startG + (int)(fraction * (endG - startG))) << 8) |
  18. (int)((startB + (int)(fraction * (endB - startB))));
  19. }
  20. }

有关它具体实现的原理。前面篇章中我们已经讲过了,这里主要说一点。ArgbEvaluator的返回值是Integer类型,所以我们要使用ArgbEvaluator的话,构造ObjectAnimator时必须使用ofInt()
以下我们来看看使用ArgbEvaluator的代码:

  1. ObjectAnimator animator = ObjectAnimator.ofInt(tv, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
  2. animator.setDuration(8000);
  3. animator.setEvaluator(new ArgbEvaluator());
  4. animator.start();

然后我们来看下代码效果:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="" />

源代码在文章底部给出

2、其他函数

以下把其他所涉及到的函数的列表列在以下。大家能够參考ValueAnimator的使用方法来使用。有关自己定义插值器和Evaluator的部分,能够參考《Animation动画具体解释(五)——高级进阶(一)》

(1)、经常使用函数

  1. /**
  2. * 设置动画时长,单位是毫秒
  3. */
  4. ValueAnimator setDuration(long duration)
  5. /**
  6. * 获取ValueAnimator在运动时。当前运动点的值
  7. */
  8. Object getAnimatedValue();
  9. /**
  10. * 開始动画
  11. */
  12. void start()
  13. /**
  14. * 设置循环次数,设置为INFINITE表示无限循环
  15. */
  16. void setRepeatCount(int value)
  17. /**
  18. * 设置循环模式
  19. * value取值有RESTART,REVERSE,
  20. */
  21. void setRepeatMode(int value)
  22. /**
  23. * 取消动画
  24. */
  25. void cancel()

(2)、监听器相关

  1. /**
  2. * 监听器一:监听动画变化时的实时值
  3. */
  4. public static interface AnimatorUpdateListener {
  5. void onAnimationUpdate(ValueAnimator animation);
  6. }
  7. //加入方法为:public void addUpdateListener(AnimatorUpdateListener listener)
  8. /**
  9. * 监听器二:监听动画变化时四个状态
  10. */
  11. public static interface AnimatorListener {
  12. void onAnimationStart(Animator animation);
  13. void onAnimationEnd(Animator animation);
  14. void onAnimationCancel(Animator animation);
  15. void onAnimationRepeat(Animator animation);
  16. }
  17. //加入方法为:public void addListener(AnimatorListener listener)

(3)、插值器与Evaluator

  1. /**
  2. * 设置插值器
  3. */
  4. public void setInterpolator(TimeInterpolator value)
  5. /**
  6. * 设置Evaluator
  7. */
  8. public void setEvaluator(TypeEvaluator value)

到这里,有关ObjectAnimator的知识就讲完了,下篇再讲讲联合动画和xml中实现动画的方法。

假设本文有帮到你,记得加关注哦

源代码下载地址:

csdn:http://download.csdn.net/detail/harvic880925/9445785

github:https://github.com/harvic/BlogResForGitHub

请大家尊重原创者版权,转载请标明出处,谢谢

自己定义控件三部曲之动画篇(七)——ObjectAnimator基本使用的更多相关文章

  1. 自己定义控件三部曲之动画篇(十三)——实现ListView Item进入动画

    前言:宝剑锋从磨砺出,梅花香自苦寒来 相关文章: <Android自己定义控件三部曲文章索引>: http://blog.csdn.net/harvic880925/article/det ...

  2. 自己定义控件三部曲视图篇(二)——FlowLayout自适应容器实现

    前言:我最大的梦想,就是有一天.等老了坐在摇椅上回望一生,有故事给孩子们讲--. 相关文章: <Android自己定义控件三部曲文章索引>:http://blog.csdn.net/har ...

  3. android--------自定义控件 之 基本流程篇

    在我们平常的Android开发中经常和控件打交道,有时Android提供的控件未必能满足业务的需求,这个时候就需要我们实现自定义一些控件 自定义控件可以设计出很多你想要的功能和模块,在开发中是很重要的 ...

  4. android--------自定义控件 之 基本实现篇

    前面简单的讲述了Android中自定义控件中的几个方法,今天通过代码来实现一个简单的案例 自定义一个扇形图 自定义控件示例: 这里先介绍继承View的方式为例 public class Circula ...

  5. 自己定义控件 播放GIF动画

    watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/ ...

  6. Android自己定义控件之应用程序首页轮播图

    如今基本上大多数的Android应用程序的首页都有轮播图.就是像下图这种(此图为转载的一篇博文中的图.拿来直接用了): 像这种组件我相信大多数的应用程序都会使用到,本文就是自己定义一个这种组件,能够动 ...

  7. Android自己定义控件:进度条的四种实现方式

    前三种实现方式代码出自: http://stormzhang.com/openandroid/2013/11/15/android-custom-loading/ (源代码下载)http://down ...

  8. 转:自定义控件三部曲之动画篇——alpha、scale、translate、rotate、set的xml属性及用法

    第一篇: 一.概述 Android的animation由四种类型组成:alpha.scale.translate.rotate,对应android官方文档地址:<Animation Resour ...

  9. 自己定义控件事实上非常easy1/6

    尊重原创转载请注明:From AigeStudio(http://blog.csdn.net/aigestudio)Power by Aige 侵权必究! 炮兵镇楼 上一节我们粗略地讲了下怎样去实现我 ...

随机推荐

  1. mybatis中if标签判断字符串相等问题

    mybatis 映射文件中,if标签判断字符串sfyx变量是否是字符串Y的时候,发现并不管用: <if test="sfyx=='Y' "> and 1=1 </ ...

  2. php文件,文件夹

    例子代码:<?php$f='/www/htdocs/index.html';$path_parts = pathinfo($f);echo $path_parts['dirname'], &qu ...

  3. [Apple开发者帐户帮助]六、配置应用服务(2)创建DeviceCheck私钥

    要验证与DeviceCheck服务的通信,您将使用启用了DeviceCheck的私钥. 首先创建并下载启用了DeviceCheck 的私钥.然后获取密钥标识符(kid)以创建JSON Web令牌(JW ...

  4. selenium3 + python - expected_conditions判断元素

    expected_conditions 类 title_is: 判断当前页面的title是否完全等于(==)预期字符串,返回布尔值 title_contains : 判断当前页面的title是否包含预 ...

  5. jQuery获取及设置单选框、多选框、文本框

    获取一组radio被选中项的值 var item = $("input[@name=items][@checked]").val(); 获取select被选中项的文本 var it ...

  6. 看懂SqlServer执行计划

    在园子看到一篇SQLServer关于查询计划的好文,激动啊,特转载.原文出自:http://www.cnblogs.com/fish-li/archive/2011/06/06/2073626.htm ...

  7. C++:C++在图片特定区域之外产生随机数

    参考原文:C++产生随机数 (整数) C++在图片特定区域之外产生随机数,避开正则表达式,可以分为两种情况. 第一种:在某个数之前生成随机数:第二种,生成随机数,加上某个数,然后截断:第三种,指定范围 ...

  8. excel 打开显示安装office自定义项 安装期间出错的解决方法

    用管理员身份运行EXCEL,转到COM加载项,删除对应加载项,即可. 注:上下两张图中的加载项信息不一致,仅作图示参考.

  9. Python学习①. 基础语法

    Python 简介 Python 是一种解释型,面向对象的语言.特点是语法简单,可跨平台 Python 基础语法 交互式编程 交互式编程不需要创建脚本文件,是通过 Python 解释器的交互模式进来编 ...

  10. beetl模板入门例子

    加入maven依赖 <dependency> <groupId>org.beetl</groupId> <artifactId>beetl-core&l ...