zoukankan      html  css  js  c++  java
  • android 开发 View _3_ View的属性动画ValueAnimator

    ValueAnimator

    ValueAnimator继承自抽象类Animator。要让属性动画渐变式地更改对象中某个属性的值,可分两步操作:第一步,动画需要计算出某一时刻属性值应该是多少;第二步,需要将计算出的属性值赋值给动画的属性。ValueAnimator只实现了第一步,也就是说ValueAnimator只负责以动画的形式不断计算不同时刻的属性值,但需要我们开发者自己写代码将计算出的值通过对象的setXXX等方法更新对象的属性值。

    ValueAnimator中有两个比较重要的属性,一个是TimeInterpolator类型的属性,另一个是TypeEvaluator类型的属性。TimeInterpolator指的就是时间插值器,在上面我们已经介绍过,在此不再赘述。TypeEvaluator是什么呢?TypeEvaluator表示的是ValueAnimator对哪种类型的值进行动画处理。ValueAnimator提供了四个静态方法ofFloat()、ofInt()、ofArgb()和ofObject(),通过这四个方法可以对不同种类型的值进行动画处理,这四个方法对应了四种TypeEvaluator,下面会详细说明。

    • public static ValueAnimator ofFloat (float… values) 
      ofFloat方法接收一系列的float类型的值,其内部使用了FloatEvaluator。通过该方法ValueAnimator可以对float值进行动画渐变,其使用方法如下所示:

        ValueAnimator valueAnimator = ValueAnimator.ofFloat(0f, 500f);
       
          valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                  float deltaY = (float)animation.getAnimatedValue();
                  textView.setTranslationY(deltaY);
              }
          });
       
          //默认duration是300毫秒
          valueAnimator.setDuration(3000);
          valueAnimator.start();

      其效果如下所示: 

      我们通过构造函数指定了动画的起始值为0,终止值为500,动画的默认持续时间是300毫秒,我们通过setDuration()方法设置为3000毫秒。该动画会在3秒内,将值从0到500动画渐变。ValueAnimator提供了一个addUpdateListener方法,可以通过该方法向其添加AnimatorUpdateListener类型的监听器。AnimatorUpdateListener有一个onAnimationUpdate方法,ValueAnimator会每隔一定时间(默认间隔10ms)计算属性的值,每当计算的时候就会回调onAnimationUpdate方法。在该方法中,我们通过调用ValueAnimator的getAnimatedValue()方法获取到当前动画计算出的属性值,然后我们将该值传入textView的setTranslationY()方法中,从而更新了textView的位置,这样就通过ValueAnimator以动画的形式移动textView。

    • public static ValueAnimator ofInt (int… values) 

      ofInt方法与ofFloat方法很类似,只不过ofInt方法接收int类型的值,ofInt方法内部使用了IntEvaluator,其具体使用可参考上面ofFloat的使用代码,在此不再赘述。

    • public static ValueAnimator ofArgb (int… values) 

      从API Level 21开始,ValueAnimator中加入了ofArgb方法,该方法接收一些列代表了颜色的int值,其内部使用了ArgbEvaluator,可以用该方法实现将一个颜色动画渐变到另一个颜色,我们从中可以不断获取中间动画产生的颜色值。你可能纳闷,既然传入的还是int值,那直接用ofInt方法不就行了吗,干嘛还要新增一个ofArgb方法呢?实际上用ofInt方法是不能完成颜色动画渐变的。我们知道一个int值包含四个字节,在Android中第一个字节代表Alpha分量,第二个字节代表Red分量,第三个字节代表Green分量,第四个字节代表Blue分量,且我们常用16进制表示颜色,这样看起来更明显易懂一些,比如int值0xffff0000表示的红色,0xff00ff00表示的是绿色,最前面的ff表示的是Alpha。ofArgb方法会通过ArgbEvaluator将颜色拆分成四个分量,然后分别对各个分量进行动画计算,然后将四个计算完的分量再重新组合成一个表示颜色的int值,这就是ofArgb方法的工作原理。使用方法如下所示:

      //ValueAnimator.ofArgb()方法是在API Level 21中才加入的
              if(Build.VERSION.SDK_INT >= 21){
                  //起始颜色为红色
                  int startColor = 0xffff0000;
                  //终止颜色为绿色
                  int endColor = 0xff00ff00;
                  ValueAnimator valueAnimator = ValueAnimator.ofArgb(startColor, endColor);
                  valueAnimator.setDuration(3000);
                  valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
                      @Override
                      public void onAnimationUpdate(ValueAnimator animation) {
                          int color = (int)animation.getAnimatedValue();
                          textView.setBackgroundColor(color);
                      }
                  });
                  valueAnimator.start();
              }

      效果如下所示: 

      我们将TextView的颜色通过动画从红色渐变到绿色。

    • public static ValueAnimator ofObject (TypeEvaluator evaluator, Object… values) 
      由于我们要进行动画处理的值是各种各样的,可能不是float、int或颜色值,那我们怎么使用属性动画呢?为此,ValueAnimator提供了一个ofObject方法,该方法接收一个TypeEvaluator类型的参数,我们需要实现该接口TypeEvaluator的evaluate方法,只要我们实现了TypeEvaluator接口,我们就能通过ofObject方法处理任意类型的数据。我们之前提到ofArgb方法是从API Level 21才引入的,如果我们想在之前的这之前的版本中使用ofArgb的功能,怎么办呢?我们可以扩展TypeEvaluator,从而通过ofObject方法实现ofArgb方法的逻辑,如下所示:

       //起始颜色为红色
          int startColor = 0xffff0000;
          //终止颜色为绿色
          int endColor = 0xff00ff00;
          ValueAnimator valueAnimator = ValueAnimator.ofObject(new TypeEvaluator() {
              @Override
              public Object evaluate(float fraction, Object startValue, Object endValue) {
                  //从初始的int类型的颜色值中解析出Alpha、Red、Green、Blue四个分量
                  int startInt = (Integer) startValue;
                  int startA = (startInt >> 24) & 0xff;
                  int startR = (startInt >> 16) & 0xff;
                  int startG = (startInt >> 8) & 0xff;
                  int startB = startInt & 0xff;
       
                  //从终止的int类型的颜色值中解析出Alpha、Red、Green、Blue四个分量
                  int endInt = (Integer) endValue;
                  int endA = (endInt >> 24) & 0xff;
                  int endR = (endInt >> 16) & 0xff;
                  int endG = (endInt >> 8) & 0xff;
                  int endB = endInt & 0xff;
       
                  //分别对Alpha、Red、Green、Blue四个分量进行计算,
                  //最终合成一个完整的int型的颜色值
                  return (int)((startA + (int)(fraction * (endA - startA))) << 24) |
                          (int)((startR + (int)(fraction * (endR - startR))) << 16) |
                          (int)((startG + (int)(fraction * (endG - startG))) << 8) |
                          (int)((startB + (int)(fraction * (endB - startB))));
              }
          }, startColor, endColor);
          valueAnimator.setDuration(3000);
          valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
              @Override
              public void onAnimationUpdate(ValueAnimator animation) {
                  int color = (int)animation.getAnimatedValue();
                  textView.setBackgroundColor(color);
              }
          });
          valueAnimator.start();

      以上代码实现的效果与ofArgb实现的效果是一样的,都是将TextView从红色渐变到绿色,但是我们可以在API Level 11及以后的版本中都可以使用以上ofObject的代码,通用性更强。

    • 效果图:


  • 相关阅读:
    springboot项目下载文件功能中-切面-导致的下载文件失败的bug
    解决laydate动态设置初始值的问题
    简易MySQL存储过程
    css选择器(第n个类选择器)的坑
    session过期情况下ajax请求不会触发重新登录的问题
    session过期情况下ajax请求不会触发重新登录的问题
    springboot配置多数据源mongodb
    css平移动画的实现
    springboot中使用JOIN实现关联表查询
    解决springboot项目中@Value注解参数值为null的问题
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/9708603.html
Copyright © 2011-2022 走看看