Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator

属性动画在API 11推出,目的是弥补帧动画和补间动画的不足,回顾其常用的使用方式。

      • 使用ViewPropertyAnimator
      • 使用ObjectAnimator
        • ofFloat方法
        • ofInt方法
        • ofArgb方法
        • ofObject方法
        • ofPropertyValuesHolder方法
          • ofKeyframe
        • addListener
        • addUpdateListener
        • 其他方法

使用ViewPropertyAnimator
ViewPropertyAnimator可以直接使用View对象进行链式调用,能够比较方便的创建动画。
编写一个简单的例子,布局:

设置动画:
Button btn = findViewById(R.id.bt_animation); float x = btn.getTranslationX(); btn.animate()//获取ViewPropertyAnimator对象 .translationX(x)//从当前位置移动 .translationX(400)//移动到400px .setDuration(2000)//动画执行时间 .start(); //开始执行动画,不调用此方法同样会执行

【Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator】运行效果:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

实际上btn.animate()返回的就是ViewPropertyAnimator对象。
ViewPropertyAnimator对象还有一些其他的常用方法:
view.animate()//获取ViewPropertyAnimator对象 //位移 .translationX(100) .translationXBy(100) .translationY(100) .translationYBy(100) .translationZ(100)//Z轴移动,API 21 添加 .translationZBy(100)//API 21 添加 //改变坐标 .x(100) .xBy(100) .y(100) .yBy(100) //改变透明度 .alpha(0.1f) .alphaBy(0.1f) //改变透明度 .scaleX(0.1f) .scaleXBy(0.1f) .scaleY(0.1f) .scaleYBy(0.1f) //旋转 .rotation(180) .rotationX(180) .rotationBy(180) .rotationY(180) .rotationYBy(180) //持续时间 .setDuration(1000) .withStartAction(new Runnable() { @Override public void run() {} })//动画开始时执行runnable,API 16添加 .withEndAction(new Runnable() { @Override public void run() {} })//动画结束时执行runnable,API 16添加.withLayer()//硬件加速,API 16添加.setStartDelay(1000)//执行延迟 //设置插值器 .setInterpolator(new LinearInterpolator()) //设置更新监听 .setUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) {} }) //动画监听 .setListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {}@Override public void onAnimationEnd(Animator animation) {}@Override public void onAnimationCancel(Animator animation) {}@Override public void onAnimationRepeat(Animator animation) {} }) .start();

其中不带By和带By的方法区别:
.translationX(100)//直接移动到指定位置 .translationXBy(100)//在之前的位置基础上移动指定距离 //其他方法以此类推...

使用ObjectAnimator
ObjectAnimator其实是属性动画最常用的类,基本能满足日常动画编写。ObjectAnimator封装了一系列的of方法,根据实际情况来选用。
API 27of系列方法:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

ofFloat方法 首先看一个简单的例子:
Button btn = findViewById(R.id.bt_animation); float x = btn.getTranslationX(); ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", x, 400); animator.setDuration(2000); animator.start();

说明其参数意义:
- btn为执行动画的对象,这里是Button按钮;
- translationX为需要操作的动画属性;
- x,400 为操作的起始值和结束值,中间还可插入一系列的数值,来满足动画的灵活变化;
同时ObjectAnimator单独提供了setFloatValues(float... values)方法,但是如果使用此方法
会将之前设置的第一组values替换掉,需要注意一下。
ObjectAnimator还可以设置插值器:
Button btn = findViewById(R.id.bt_animation); float x = btn.getTranslationX(); ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", x, 400); animator.setInterpolator(new AccelerateInterpolator()); //加速插值器 animator.setDuration(1000); animator.start();

执行效果:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

API 27为止包含的系统插值器:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

使用Property封装的方法:
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, Property.of(Button.class, Float.class, "translationX"), x, 400); animator.setDuration(2000); animator.start();

另外API 21 增加了Path对象,这样可以执行更为复杂灵活的动画效果:
Button btn = findViewById(R.id.bt_animation); Path path = new Path(); path.moveTo(btn.getX(),btn.getY()); path.lineTo(400,400); //API 21 添加 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ObjectAnimator animator = ObjectAnimator.ofFloat(btn, "translationX", "translationY", path); animator.setDuration(2000); animator.start(); }

说明下该方法的参数:
ObjectAnimator.ofFloat(Object target, String xPropertyName, String yPropertyName, Path path)

  • target动画执行的对象
  • xPropertyNameX轴坐标
  • yPropertyNameY轴坐标
  • Path绘制动画路径类
API 21也可以使用PropertyPath参数的方法:
ObjectAnimator animator = ObjectAnimator.ofFloat(btn, Property.of(Button.class, Float.class, "translationX"), Property.of(Button.class, Float.class, "translationY"), path); animator.setDuration(2000); animator.start();

使用带TypeEvaluator估值器参数的方法:
ObjectAnimator animator = ObjectAnimator.ofObject(btn, "translationX", new FloatEvaluator(), x, 400); animator.setDuration(2000); animator.start();

API 27为止,系统已经实现的估值器:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

ofInt方法 基本同ofFloat方法一致。
ofArgb方法 在API 21ObjectAnimator单独提供ofArgb方法用于方便进行颜色动画的过渡计算:
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { ObjectAnimator .ofArgb(btn, "backgroundColor", Color.parseColor("#ff0000"),//红色 Color.parseColor("#0000ff"))//蓝色 .setDuration(2000) .start(); }

执行由红变蓝的效果:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

ofObject方法 另外ObjectAnimator还有ofObject的一些方法:
ObjectAnimator .ofObject(btn,"translationX",new FloatEvaluator(),x,400) .setDuration(2000) .start();

上面这这段代码同样可以实现平移效果,看下该方法的参数:
public static ObjectAnimator ofObject(Object target, String propertyName, TypeEvaluator evaluator, Object... values)

  • target动画执行的对象
  • PropertyName属性名
  • TypeEvaluator估值器
  • values动画执行的可变参数
    这里需要注意的是TypeEvaluator中的evaluate()方法返回类型必须和values的参数类型一致,因为这里没有进行泛型约束,因此需要特别注意,该方法主要可以用于自定义的TypeEvaluatorvalues,因此在执行动画过程中,需要保证类型一致。
ofPropertyValuesHolder方法 ObjectAnimator还提供了非常重要的ofPropertyValuesHolder系列方法,使用PropertyValuesHolder参数可以使多个动画同时执行:
PropertyValuesHolder p1 = PropertyValuesHolder.ofFloat("translationX", x, 400); PropertyValuesHolder p2 = PropertyValuesHolder.ofFloat("translationY", y, 400); ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(btn, p1, p2); animator.setDuration(2000); animator.start();

PropertyValuesHolder其实就是封装了要执行动画改变的属性和一系列的变化值,并且也拥有和ObjectAnimator类似的各种ofIntofFloatofObject等方法。
ofKeyframe ofKeyframe的方法可以设置动画的关键帧:
Keyframe k1 = Keyframe.ofFloat(0, x); Keyframe k2 = Keyframe.ofFloat(0.5f, 100); Keyframe k3 = Keyframe.ofFloat(1f, 400); PropertyValuesHolder holder = PropertyValuesHolder.ofKeyframe("translationX", k1, k2, k3); ObjectAnimator.ofPropertyValuesHolder(btn,holder).setDuration(2000).start();

Keyframe.ofFloat(float fraction, float value)方法中fraction代表动画执行的进度(0-1之间),value代表这个进度需要执行的数值,也就是一帧的意思。
看下执行效果:
Android|属性动画使用解析(一):ViewPropertyAnimator和ObjectAnimator
文章图片

另外Keyframe也可以设置插值器,和ObjectAnimator比较类似,这里不再列出。
但是需要注意的是如果使用Keyframe则必须至少有2帧添加到PropertyValuesHolder中,否则会抛出异常:
java.lang.ArrayIndexOutOfBoundsException: length=1; index=1
addListener 可以添加动画周期中的监听回调:
objectAnimator.addListener(new Animator.AnimatorListener() { @Override public void onAnimationStart(Animator animation) {}@Override public void onAnimationEnd(Animator animation) {}@Override public void onAnimationCancel(Animator animation) {}@Override public void onAnimationRepeat(Animator animation) {} });

如果直接使用Animator.AnimatorListener参数,需要实现的方法较多,可以选择AnimatorListenerAdapter,它实现了Animator.AnimatorListener接口,可以有选择的实现需要的接口。
addUpdateListener 该方法可以获取更新中的ValueAnimator对象,从而获取其中包含的相关信息,编写业务逻辑。
objectAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() { @Override public void onAnimationUpdate(ValueAnimator animation) { } });

其他方法 setRepeatCount:就是设置动画执行次数;
setRepeatMode:设置重复模式 RESTART,REVERSE,INFINITE;
setStartDelay:设置动画执行延迟;
其他还有些方法,不一一分析了。

    推荐阅读