今天给大家介绍PropertyValuesHolder和Keyframe,在动画中也是属于比较重要的东西,请大家细品,接下来步入主题
- 概述
- 先看看本篇要实现的效果吧
- PropertyValuesHolder
- ofInt(),ofFloat()和ofObject()
- Keyframe.ofObject();
概述
前几篇给大家介绍了ObjectAnimator的ofInt(),ofFloat()ofObject()方法,这篇给大家带来ObjectAnimator.ofPropertyValuesHolder();方法的介绍和简单的使用
先看看本篇要实现的效果吧
PropertyValuesHolder
介绍:
PropertyValuesHolder类相当于一个动画容器,主要作用就是用来存放属性对应的值与属性的.他的作用和animatorSet()有点类似.大家吧他当做animatorSet()方法就好.不一样的地方就是ofPropertyValuesHolder()是ObjectAnimator的静态方法;
有参构造
- PropertyValuesHolder ofint = PropertyValuesHolder.ofInt(String propertyName, int… values)
- PropertyValuesHolder offloat = PropertyValuesHolder.ofFloat(String propertyName, float… values)
- PropertyValuesHolder ofObject = PropertyValuesHolder.ofObject(String propertyName, TypeEvaluator evaluator,
Object… values)- PropertyValuesHolder ofKeyFream = PropertyValuesHolder.ofKeyfream(String propertyName, Keyframe… values)
- 参数一:需要设置的动画属性
- 参数二:可变参数,用来设置动画值,比如现在动画属性是\”scaleX\”,1代表本身不变,1.5则代表相对于X轴方法1.5倍,0.5则代表相对于X轴缩小0.5倍.以此类推
ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(Object target,
PropertyValuesHolder… values);
参数一:需要设置的控件
参数二:可变参数,可添加多个PropertyValuesHolder对象
ofInt(),ofFloat()和ofObject()
先来康康要实现的效果:
这里就同时用到了:
- ofObject()设置A-Z显示,
- ofFloat()设置Y轴缩放,
- ofInt()改变背景颜色
先看看代码在一步一步讲解:
PropertyValuesHolder TextTitle = PropertyValuesHolder.ofObject(\"TextTitle\",new MyEvaluator(), new Character(\'A\'), new Character(\'Z\'));PropertyValuesHolder backgroundColor = PropertyValuesHolder.ofInt(\"backgroundColor\",0xffff00ff,0xffffff00,0xff00ff00,0xff00f0f0);PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat(\"scaleY\",1.1f,1,5,1f,7f,1f);ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(myTextView, TextTitle,backgroundColor,scaleY);objectAnimator.setDuration(3000);objectAnimator.start();
PropertyValuesHolder.ofObject(\"TextTitle\",new MyEvaluator(), new Character(\'A\'), new Character(\'Z\'));
- 参数一介绍:
这里使用到了ofObject()实现从A-Z依次显示,第一个参数中需要一个set方法,所以就必须先定义一个类,继承自TextView,实现setTextTitle()方法
public class MyTextView extends TextView {public MyTextView(Context context) {super(context);}public MyTextView(Context context, @Nullable AttributeSet attrs) {super(context, attrs);}//因为A - Z依次显示的是char类型的,所以这里类型只能使用characterset后边的TextTitle就是ofObject()中的参数一;public void setTextTitle(Character c){setText(String.valueOf(c));}}
因为咋们并没有对这个自定义View做什么,并且它是继承自TextView的,所以咋们就当做它是TextView使用即可.
- 参数二介绍:
前几篇讲过这个TypeEvaluator,这是一个加速器,这里就不在重复讲解了,如有需要可以点击 查看.Evaluator来进行了解.这里直接贴代码了.
public class MyEvaluator implements TypeEvaluator<Character> {@Override //当前的进度, 开始的值 结束的值public Character evaluate(float fraction, Character startValue,Character endValue) {int end = endValue;int start = startValue;int a = (int) (start + ( fraction * (end - start)));char b = (char) a;return b;}}公式:当前进度 = 最小值 + (进度 * (最大值 - 最小值))
这个和ObjectAnimator.ofFloat(),ObjectAnimator.ofInt()用法完全相同,这里就不在讲解了PropertyValuesHolder backgroundColor = PropertyValuesHolder.ofInt(\"backgroundColor\",0xffff00ff,0xffffff00,0xff00ff00,0xff00f0f0);PropertyValuesHolder scaleY = PropertyValuesHolder.ofFloat(\"scaleY\",1.1f,1,5,1f,7f,1f);
这里肯定有朋友有所疑问什么时候用ofInt(),什么时候用Float()呢?
- 是动画属性的时候有用ofFloat()其余的都用ofInt(),什么是动画属性呢?,就比如旋转,移动,透明,缩放,这些用ofFloat(),除这些以外,比如设置个背景颜色\”backgroundColor\”就用ofInt().
KeyFream
KeyFream是关键帧的意思,通过key和value的形式,将值传入ofKeyFream(String propertyName, Keyframe… values)中.
先看看要实现的效果:
有参构造:
- KeyFrame.OfFloat(String propertyName, Keyframe… values)
- Keyframe scaleKeyframe = KeyFrame.OfFloat(String propertyName)
通过scaleKeyframe.setValue()来设置Value
咋们先看看KeyFrame.OfFloat()方法的源码注释:
参数一:时间,用0到1之间的值表示,表示分数 整个动画持续时间的时间。
参数二: 要设置的关键帧值
咋们先定义11个keyFragme.ofFloat(),代表把所设置时间分为10份,每一份作对应的值.
Keyframe scaleKeyframe = Keyframe.ofFloat(0f, 0);Keyframe scaleKeyframe1 = Keyframe.ofFloat(0.1f, 1.1f);Keyframe scaleKeyframe2 = Keyframe.ofFloat(0.2f, 1.2f);Keyframe scaleKeyframe3 = Keyframe.ofFloat(0.3f, 1.2f);Keyframe scaleKeyframe4 = Keyframe.ofFloat(0.4f, 1.1f);Keyframe scaleKeyframe5 = Keyframe.ofFloat(0.5f, 2f);Keyframe scaleKeyframe6 = Keyframe.ofFloat(0.6f, 1.2f);Keyframe scaleKeyframe7 = Keyframe.ofFloat(0.7f, 1.1f);Keyframe scaleKeyframe8 = Keyframe.ofFloat(0.8f, 1.1f);Keyframe scaleKeyframe9 = Keyframe.ofFloat(0.9f, 1.2f);Keyframe scaleKeyframe10 = Keyframe.ofFloat(1f, 1);PropertyValuesHolder scale = PropertyValuesHolder.ofKeyframe(\"scaleX\",scaleKeyframe, scaleKeyframe1, scaleKeyframe2, scaleKeyframe3, scaleKeyframe4,scaleKeyframe5, scaleKeyframe6, scaleKeyframe7, scaleKeyframe8, scaleKeyframe9, scaleKeyframe10);ObjectAnimator objectAnimator1 = ObjectAnimator.ofPropertyValuesHolder(tv, scale);objectAnimator1.setDuration(3000);objectAnimator1.start();
来康康效果吧:
这里可以看出,效果还是很明显的,咋们这里设置的动画时间是3s,在时间进行到一半(0.5)的时候,相对于X轴放大2倍.
这里设置了11帧,如果设置1帧会出现什么情况呢?
这里只设置在进度走40%的时候,变大2倍Keyframe scaleKeyframe4 = Keyframe.ofFloat(0.4f, 2f);
来康康效果吧:
可以看出,如果只设置一帧的话,会出现下标越界,那咋们继续,在加一帧,给他一个开始帧,和一个结束帧看看有什么效果吧:
Keyframe scaleKeyframe4 = Keyframe.ofFloat(0.4f, 2f);Keyframe scaleKeyframe8 = Keyframe.ofFloat(0.8f, 1.1f);
这里设置在40%的时候,X轴变大2倍,然后依次缩小到80%的时候,变化到1.1倍
来看看效果~
大家可以看到,如果这样设置的话,开始帧就是从40%处开始,并且结束的时候会返回到最开始的状态
现在已经有2种情况需要注意:
- 必须有2帧以上,开始帧和结束帧
- 开始帧是从设置进度开始的而不是从0的进度开始
我还想到一种情况,若开始帧不是0-1之间若>1会是什么效果呢?,接下来就带大家一起看看实验一下,看看效果吧:
Keyframe scaleKeyframe4 = Keyframe.ofFloat(0.4f, 2f);Keyframe scaleKeyframe8 = Keyframe.ofFloat(0.8f, 1.1f);Keyframe scaleKeyframe9 = Keyframe.ofFloat(1f, 1f);Keyframe scaleKeyframe10 = Keyframe.ofFloat(2.5f, 3f);
为了效果明显,我把最后一个设置为扩大三倍:
很明显,设置的250%进度并没有效果,所以得出一下结论:
- 必须有2帧以上,开始帧和结束帧
- 开始帧是从设置进度开始的而不是从0的进度开始
- 设置进度必须在0-1之间,否则会没有效果
Keyframe.ofObject();
先来看看实现的效果吧:
直接上代码
Keyframe objectKetframeA = Keyframe.ofObject(0, \'A\');Keyframe objectKetframeC = Keyframe.ofObject(0.3f, \'C\');Keyframe objectKetframeZ = Keyframe.ofObject(1f, \'Z\');PropertyValuesHolder textTitle = PropertyValuesHolder.ofKeyframe(\"TextTitle\", objectKetframeA, objectKetframeC, objectKetframeZ);textTitle.setEvaluator(new MyEvaluator());ObjectAnimator objectAnimator = ObjectAnimator.ofPropertyValuesHolder(myTextView, textTitle);objectAnimator.setDuration(3000);objectAnimator.start();
其实他们的用法都基本很相似,这里的关键帧设置的是当进度走到30%的时候,显示C,然后在剩下的70%进度中走到Z,
在效果图中也可以很明显的看到事实确实如此.这里的TextTitle和MyEvaluator()用过很多次,就不在重复啰嗦了.
最后来完成咋们本篇开始的效果:
直接上代码:
Keyframe keyframe = Keyframe.ofFloat(0f, 0);Keyframe keyframe1 = Keyframe.ofFloat(0.1f, 20f);Keyframe keyframe2 = Keyframe.ofFloat(0.2f, -20f);Keyframe keyframe3 = Keyframe.ofFloat(0.3f, 40f);Keyframe keyframe4 = Keyframe.ofFloat(0.4f, -40f);Keyframe keyframe5 = Keyframe.ofFloat(0.5f, 20f);Keyframe keyframe6 = Keyframe.ofFloat(0.6f, -20f);Keyframe keyframe7 = Keyframe.ofFloat(0.7f, 40f);Keyframe keyframe8 = Keyframe.ofFloat(0.8f, -40f);Keyframe keyframe9 = Keyframe.ofFloat(0.9f, 20f);Keyframe keyframe10 = Keyframe.ofFloat(1f, 0);Keyframe scaleKeyframe = Keyframe.ofFloat(0f, 0);Keyframe scaleKeyframe1 = Keyframe.ofFloat(0.1f, 1.1f);Keyframe scaleKeyframe2 = Keyframe.ofFloat(0.2f, 1.2f);Keyframe scaleKeyframe3 = Keyframe.ofFloat(0.3f, 1.2f);Keyframe scaleKeyframe4 = Keyframe.ofFloat(0.4f, 2f);Keyframe scaleKeyframe5 = Keyframe.ofFloat(0.5f, 2f);Keyframe scaleKeyframe6 = Keyframe.ofFloat(0.6f, 1.2f);Keyframe scaleKeyframe7 = Keyframe.ofFloat(0.7f, 1.1f);Keyframe scaleKeyframe8 = Keyframe.ofFloat(0.8f, 1.1f);Keyframe scaleKeyframe9 = Keyframe.ofFloat(0.9f, 1.5f);Keyframe scaleKeyframe10 = Keyframe.ofFloat(1f, 1f);PropertyValuesHolder rotation = PropertyValuesHolder.ofKeyframe(\"rotation\",keyframe, keyframe1, keyframe2, keyframe3, keyframe4,keyframe5, keyframe6, keyframe7, keyframe8, keyframe9, keyframe10);PropertyValuesHolder scale = PropertyValuesHolder.ofKeyframe(\"scaleX\",scaleKeyframe, scaleKeyframe1, scaleKeyframe2, scaleKeyframe3, scaleKeyframe4,scaleKeyframe5, scaleKeyframe6, scaleKeyframe7, scaleKeyframe8,scaleKeyframe9, scaleKeyframe10);ObjectAnimator objectAnimator1 = ObjectAnimator.ofPropertyValuesHolder(tv, rotation,scale);objectAnimator1.setDuration(3000);objectAnimator1.start();
我相信通过上面的讲解,这段代码还是能看明白的,本篇有点长,可能有讲的不到位的地方,请大家多多包涵,有大佬有不同意见,欢迎在评论区留言哦~
参考文档:链接: 启舰.
git地址:链接: langyangyang.