Android属性动画ViewPropertyAnimator、
2019-02-18 本文已影响0人
飞奔吧牛牛
属性动画的三种方式
1.ViewPropertyAnimator
直接使用View.animate() 获取 ViewPropertyAnimator 对象,只能使用api提供的动画,总体来说有四类:
animate.translationX(500);//平移
animate.alpha(0.6f);//透明度
animate.rotation(90);//旋转
animate.scaleX(0.1f);//缩放
2.ObjectAnimator
可以实现和上诉相同的功能,例如:
ObjectAnimator.ofFloat(tv, "translationX", 500).setDuration(2000).start();或
ObjectAnimator.ofFloat(tv, View.TRANSLATION_X, 500).setDuration(2000).start();
View中存在setter和getter方法的属性才可以进行动画。如View中存在setTranslationX()和getTranslationX()方法。
但有些属性是View中没有的,比如控件的宽度width,它存在于LayoutParam中。如果要对控件宽度进行动画处理应该怎么办呢?
1.可以使用包装类来提供这个属性。
第一步:
class MyViewWapper {
private View v;
public MyViewWapper(View v) {
this.v = v;
}
public int getWidth() {
return v.getLayoutParams().width;
}
public void setWidth(int width) {
v.getLayoutParams().width = width;
v.requestLayout();
}
}
第二步:
ObjectAnimator.ofInt(new MyViewWapper(tv), "width", 500).setDuration(2000).start();
2.如果是自定义View,直接将setter和getter写在类中即可。
注意:ObjectAnimator并不是去目标对象中找和“width”一样的同名成员变量,而是拼接setter和getter方法再调用,所以必须提供setWidth()/getWidth()方法。
ValueAnimator
使用ObjectAnimator可以对View中没有的属性做动画,只需要包装一个类,并提供对应的setter/getter方法。ValueAnimator可以求出两个值之间的变化值,并回调到方法中,我们在回调的方法中手动设置控件的属性即可。
ValueAnimator valueAnimator = ValueAnimator.ofInt(0, 500);
valueAnimator.setDuration(2000);
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
int animatedValue = (Integer) animation.getAnimatedValue();
tv.getLayoutParams().width = animatedValue;
tv.requestLayout();
}
});
valueAnimator.start();
补充:鉴于手机开发者模式中可以设置:动画程序时长缩放为关闭动画,使得动画不能正常执行。
可以参考:https://blog.csdn.net/u011387817/article/details/78628956 解决。
意思是开发者选项中该设置改变了ValueAnimator类中的静态成员变量:
private static float sDurationScale = 1.0f;
只要通过反射重置为1.0f即可。
public class ValueAnimatorUtil {
/**
* 如果动画被禁用,则重置动画缩放时长
*/
public static void resetDurationScaleIfDisable() {
if (getDurationScale() == 0)
resetDurationScale();
}
/**
* 重置动画缩放时长
*/
public static void resetDurationScale() {
try {
getField().setFloat(null, 1);
} catch (Exception e) {
e.printStackTrace();
}
}
private static float getDurationScale() {
try {
return getField().getFloat(null);
} catch (Exception e) {
e.printStackTrace();
return -1;
}
}
@NonNull
private static Field getField() throws NoSuchFieldException {
Field field = ValueAnimator.class.getDeclaredField("sDurationScale");
field.setAccessible(true);
return field;
}
}