转载请标明出处:http://blog.csdn.net/zhaoyanjun6/article/details/118709616 本文出自【赵彦军的博客】
ObjectAnimator
public final class ObjectAnimator extends ValueAnimator {
...
}
ObjectAnimator 继承 ValueAnimator , 所以 ObjectAnimator 拥有 ValueAnimator 一切特性。
相比于ValueAnimator ,ObjectAnimator 可能才是我们最常接触到的类,因为ValueAnimator 只不过是对值进行了一个平滑的动画过渡,但我们实际使用到这种功能的场景好像并不多。而ObjectAnimator 则就不同了,它是可以直接对任意对象的任意属性进行动画操作的,比如说View 的alpha 属性。
不过虽说ObjectAnimator 会更加常用一些,但是它其实是继承自ValueAnimator 的,底层的动画实现机制也是基于ValueAnimator来完成的,因此ValueAnimator 仍然是整个属性动画当中最核心的一个类。那么既然是继承关系,说明ValueAnimator 中可以使用的方法在ObjectAnimator 中也是可以正常使用的,它们的用法也非常类似,这里如果我们想要将一个TextView 在5秒中内从常规变换成全透明,再从全透明变换成常规,就可以这样写:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f, 1f);
animator.setDuration(5000);
animator.start();
可以看到,我们还是调用了ofFloat() 方法来去创建一个ObjectAnimator 的实例,只不过ofFloat() 方法当中接收的参数有点变化了。这里第一个参数要求传入一个object 对象,我们想要对哪个对象进行动画操作就传入什么,这里我传入了一个textview 。第二个参数是想要对该对象的哪个属性进行动画操作,由于我们想要改变TextView 的不透明度,因此这里传入"alpha" 。后面的参数就是不固定长度了,想要完成什么样的动画就传入什么值,这里传入的值就表示将TextView 从常规变换成全透明,再从全透明变换成常规。之后调用setDuration() 方法来设置动画的时长,然后调用start() 方法启动动画,效果如下图所示:
学会了这一个用法之后,其它的用法我们就可以举一反三了,那比如说我们想要将TextView 进行一次360度 的旋转,就可以这样写:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "rotation", 0f, 360f);
animator.setDuration(5000);
animator.start();
可以看到,这里我们将第二个参数改成了"rotation" ,然后将动画的初始值和结束值分别设置成0和360 ,现在运行一下代码,效果如下图所示:
那么如果想要将TextView先向左移出屏幕,然后再移动回来,就可以这样写:
float curTranslationX = textview.getTranslationX();
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "translationX", curTranslationX, -500f, curTranslationX);
animator.setDuration(5000);
animator.start();
这里我们先是调用了TextView 的getTranslationX() 方法来获取到当前TextView的translationX 的位置,然后ofFloat() 方法的第二个参数传入"translationX" ,紧接着后面三个参数用于告诉系统TextView 应该怎么移动,现在运行一下代码,效果如下图所示:
然后我们还可以TextView 进行缩放操作,比如说将TextView 在垂直方向上放大3倍再还原,就可以这样写:
ObjectAnimator animator = ObjectAnimator.ofFloat(textview, "scaleY", 1f, 3f, 1f);
animator.setDuration(5000);
animator.start();
这里将ofFloat()方法的第二个参数改成了"scaleY",表示在垂直方向上进行缩放,现在重新运行一下程序,效果如下图所示:
到目前为止,ObjectAnimator 的用法还算是相当简单吧,但是我相信肯定会有不少朋友现在心里都有同样一个疑问,就是ofFloat() 方法的第二个参数到底可以传哪些值呢?
目前我们使用过了alpha 、rotation 、translationX 和scaleY 这几个值,分别可以完成淡入淡出、旋转、水平移动、垂直缩放这几种动画,那么还有哪些值是可以使用的呢?
其实这个问题的答案非常玄乎,就是我们可以传入任意的值到ofFloat() 方法的第二个参数当中。任意的值?相信这很出乎大家的意料吧,但事实就是如此。因为ObjectAnimator 在设计的时候就没有针对于View 来进行设计,而是针对于任意对象的,它所负责的工作就是不断地向某个对象中的某个属性进行赋值,然后对象根据属性值的改变再来决定如何展现出来。
那么比如说我们调用下面这样一段代码:
ObjectAnimator.ofFloat(textview, "alpha", 1f, 0f);
其实这段代码的意思就是ObjectAnimator 会帮我们不断地改变textview 对象中alpha 属性的值,从1f变化到0f。然后textview 对象需要根据alpha 属性值的改变来不断刷新界面的显示,从而让用户可以看出淡入淡出的动画效果。
那么textview 对象中是不是有alpha 属性这个值呢?
没有,不仅textview 没有这个属性,连它所有的父类也是没有这个属性的!
这就奇怪了,textview 当中并没有alpha这个属性,ObjectAnimator 是如何进行操作的呢?其实ObjectAnimator 内部的工作机制并不是直接对我们传入的属性名进行操作的,而是会去寻找这个属性名对应的get和set 方法,因此alpha属性所对应的get和set 方法应该就是:
public void setAlpha(float value);
public float getAlpha();
那么textview 对象中是否有这两个方法呢?确实有,并且这两个方法是由View 对象提供的,也就是说不仅TextView 可以使用这个属性来进行淡入淡出动画操作,任何继承自View 的对象都可以的。
既然alpha 是这个样子,相信大家一定已经明白了,前面我们所用的所有属性都是这个工作原理,那么View当中一定也存在着setRotation() 、getRotation() 、setTranslationX() 、getTranslationX() 、setScaleY() 、getScaleY() 这些方法,不信的话你可以到View当中去找一下。
实战-心跳动画
先上效果图:
自定义 View
class MyView(context: Context?, attrs: AttributeSet?) : View(context, attrs) {
private var radius = 10f
set(value) {
field = value
invalidate()
}
private val paint = Paint()
init {
paint.color = Color.BLUE
paint.textSize = 8f
paint.isAntiAlias = true
paint.style = Paint.Style.FILL
}
override fun onDraw(canvas: Canvas?) {
super.onDraw(canvas)
canvas?.drawCircle((width / 2).toFloat(), (height / 2).toFloat(), radius, paint)
}
}
有一点很重要的是,radius 的 set 方法中需要调用 invalidate() 方法,才能够刷新view
我们再看执行动画的部分
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
var myView: MyView = findViewById(R.id.myView)
var objectAnimator =
ObjectAnimator.ofFloat(myView, "radius", 200f, 500f, 200f)
objectAnimator.duration = 600
objectAnimator.interpolator = LinearInterpolator()
objectAnimator.repeatCount = 20
objectAnimator.start()
}
}
参考资料
|