4.属性动画补充
文章目录
4.1 PropertyValuesHolder与Keyframe
- ValueAnimator和ObjecAnimator除可以通过oflnt()、ofFloat()、ofObject()函数创建实例外,还都有一个ofPropertyValuesHoIder()函数来创建实例。
4.1.1 PropertyValuesHolder
创建PropertyValuesHolder实例的函数:
public static PropertyValuesHolder ofFloat(String propertyName,float...values) public static PropertyValuesHolder ofint(String propertyName,int .. values) public static PropertyValuesHolder ofObject(String propertyName,TypeEvaluator evaluator,Object...values) public static PropertyValuesHolder ofKeyframe(String propertyName,Keyframe...values)
ObjecAnimator.ofPropertyValuesHolder():
public static ObjecAnimator ofPropertyValuesHolder(Object target, PropertyValuesHolder...values)
PropertyValuesHolder之ofObject():
public static PropertyValuesHolder ofObject(String propertyName,TypeEvaluator evaluator,Object...values)
4.1.2 Keyframe
为了方便地控制动画速率的问题, Google定义了Keyframe 类。
public static Keyframe ofFloat(float fraction , float value)
- fraction:表示当前的显示进度, 即在插值器中getlnterpolation()函数的返回值。
- value:表示动画当前所在的数值位置。
PropertyValuesHolder的ofKeyframe函数:
public static PropertyValuesHolder ofKeyframe(String propertyName, Keyframe...values)
其他函数:
public void setFraction(float fraction)//设置fraction参数,即Keyframe所对应的进度 public void setValue(Object value)//设置当前Keyframe所对应的值 public void setinterpolator(Timeinterpolator interpolator)//设置差值器 //PropertyValuesHolder的补充函数 public void setEvaluator(TypeEvaluator evaluator)//设置动画的Evaluator public void setFloatValues(float...values)//用于设置ofFloat()所对应的动画值列表 public void setintValues(int...values)//用于设置ofint()所对应的动画值列表 public void setKeyframes(Keyframe ... values )//用于设置ofKeyframe()所对应的动画值列表 public void setObjectValues(Object...values)//用于设置ofObject()所对应的动画值列表 public void setPropertyName(String propertyName)//设置动画属性名
4.2 ViewPropertyAnimator
4.2.1 概述
用法对比:
//原用法 ObjectAnimator animator = ObjectAnimator.ofFloat(textview,"alpha",0f); animator.start(); //ViewPropertyAnimator提供的API textview.animate().alpha(0f);//透明度 myView.animate().x(50).y(100);//平移
- **animate():**系统从调用View 的animate()函数开始。该函数返回一个ViewPropertyAnimator对象,可通过调用这个对象的函数来设置需要实现动画的属性。
- **自动开始:**不需显式调用过start()函数。
- **流畅(Fluent):**允许将多个函数调用串在一起,并把一个多属性的动画写成一行代码。
4.2.2 常用函数
函数 | 含义 |
---|---|
alpha(tloat value) | 设置透明度 |
scaleY(tloat value) | 设置Y轴方向的缩放大小 |
scaleX(tloat value) | 设置X轴方向的缩放大小 |
translationY(tloat value) | 设置Y轴方向的移动值 |
translationX(tloat value) | 设置X轴方向的移动值 |
rotation(float value) | 设置绕Z轴旋转度数 |
rotationX(float value) | 设置绕X轴旋转度数 |
rotationY(float value) | 设置绕Y轴旋转度数 |
x(float value) | 相对于父容器的左上角坐标在X轴方向的最终位置 |
y(float value) | 相对于父容器的左上角坐标在Y轴方向的最终位置 |
alphaBy(float value) | 设置透明度增量 |
rotationBy(float value) | 设置绕Z轴旋转增量 |
rotationXBy(float value) | 设置绕X轴旋转增量 |
rotationYBy(float value) | 设置绕Y轴旋转增量 |
translationXBy(float value) | 设置X轴方向的移动值增量 |
translationYBy(float value) | 设置Y轴方向的移动值增量 |
scaleXBy(float value) | 设置X轴方向的缩放大小增量 |
scaleYBy(float value) | 设置Y轴方向的缩放大小增量 |
xBy(float value) | 相对于父容器的左上角坐标在X轴方向的位置增量 |
yBy(float value) | 相对于父容器的左上角坐标在Y轴方向的位置增量 |
setlnterpolator(Timelnterpolator interpolator) | 设置插值器 |
setStartDelay(long startDelay) | 设置开始延时 |
setDuration(long duration) | 设置动画时长 |
4.2.3 性能考量
- ViewPropertyAnimator并没有像ObjectAnimator 一样使用反射或者JNI 技术;而ViewPropertyAnimator会根据预设的每一个动画帧计算出对应的所有属性值,并设置给控件,然后调用一次invalidate() 函数进行重绘,从而解决了在使用ObjectAnimator时每个属性单独计算、单独重绘的问题。所以ViewPropertyAnimator相对于 bjectAnimator和组合动画,性能有所提升。
- 使用ObjectAnimator时并不需要太过担心性能,使用反射和JNI 等技术所带来的开销相对于整个程序来讲都是微不足道的。使用ViewPropertyAnimator最大的优势不在于性能的提升,而是它提供的简明易读的代码书写方式。
4.3 为ViewGroup内的组件添加动画
- 方法一:layoutAnimation标签与LayoutAnimationController(有缺陷)
- 方法二:gridlayoutAnimation 标签与GridlayoutAnimationController(有缺陷)
- 方法三:android:animatelayoutChanges属’性(不能自定义动画)
- 方法四:LayoutTransition(最强大)
4.3.1 animatelayoutChanges 属性
XML中定义:
android:animateLayoutChanges="true”
代码处理:
//添加控件 private void addButtonView(){ i++; Button button= new Button(this); button.setText("button"+i) ; LinearLayout.LayoutParams params = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,ViewGroup.LayoutParams.WRAP_CONTENT); button.setLayoutParams(params); linearLayoutContainer.addView(button,0); } //删除控件 private void removeButtonView(){ if(i > 0){ linearLayoutContainer.removeViewAt(0); } i--; }
4.3.2 LayoutTransition
创建实例:
LayoutTransition transitioner = new LayoutTransition();
创建动画并进行设置:
ObjectAnimator animOut = ObjectAnimator.ofFloat(null,"rotation",0f,90f,0f); transitioner.setAnimator(LayoutTransition.DISAPPEARING,animOut); //函数原型 public void setAnimator(int transitionType,Animator animator)
- APPEARING:元素在容器中出现时所定义的动画。
- DISAPPEARING:元素在容器中消失时所定义的动画。
- CHANGE_APPEARING:由于容器中要显现一个新的元素, 其他需要变化的元素所应用的动画。(不常用,可能存在问题)
- CHANGE_DISAPPEARING : 当容器中某个元素消失时, 其他需要变化的元素所应用的动画。(不常用,可能存在问题)
将LayoutTransition设置到ViewGroup中:
linearLayout.setLayoutTransition(transitioner);
注意:(针对CHANGE_APPEARING、CHANGE_DISAPPEARING)
LayoutTransition.CHANGE_APPEARING和LayoutTransition.CHANGE_DISAPPEARING必须使用PropertyValuesHolder所构造的动画才会有效果。
在构造PropertyValuesHolder动画时,“left”、“top”属性的变动是必写的。如果不需要变动,则直接写为:
PropertyValuesHolder pvhLeft = PropertyValuesHolder.ofInt("left",0,0); PropertyValuesHolder pvhTop = PropertyValuesHolder.ofInt("top",0,0);
在构造PropertyValuesHolder动画时,所使用的ofInt()、ofFloat()函数中的参数值,第一个值和最后一个值必须相同:否则此属性所对应的动画将被放弃,在此属性值上将不会有效果。
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",1f,0f,1f);
在构造PropertyValuesHolder动画时,所使用的oflnt()、ofFloat()函数中,如果所有参数值都相同,则将不会有动画效果。比如:
PropertyValuesHolder pvhScaleX = PropertyValuesHolder.ofFloat("scaleX",100f,100f);
4.3.3 其他函数
基本设置:
/** * 设置所有动画完成所需要的时长 */ public void setDuration(long duration) /** * 针对单个Type设置动画时长; * transitionType 取值为 APPEARING、DISAPPEARING、CHANGE_APPEARING、CHANGE_DISAPPEARING */ public void setDuration(int transitionType,long duration) /** * 针对单个Type设置插值器 */ public void setInterpolator(int transitionType,TimeInterpolator interpolator) /** * 针对单个Type设置动画延时 */ public void setStartDelay(int transitionType,long delay) /** * 针对单个Type设置每个子item动画的时间间隔 */ public void setStagger(int transitionType,long duration)
设置监听:
public void addTransitionListener(TransitionListener listener) //其中: public interface TransitionListener{ public void startTransition(LayoutTransition transition,ViewGroup container, View view,int transitionType); public void endTransition(LayoutTransition transition,ViewGroup container,View view,int transitionType); }
- LayoutTransition transition :当前的LayoutTransition 实例。
- ViewGroup container:当前应用LayoutTransition的容器。
- View view:当前在做动画的View对象。
- int transitionType:当前的LayoutTransition 类型,取值有 APPEARING、DISAPPEARING、CHANGE_APPEARING和CHANGE_DISAPPEARING。
注意:
- APPEARING/DISAPPEARING:事件针对当前被添加的控件做动画,所以返回的View 是当前被添加的控件
- CHANGE_APPEARING/CHANGE_DISAPPEARING:事件针对容器中所有已经存在的控件做动画,所以返回的View是容器。
参考资料
- 《Android自定义控件开发入门与实战》