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的代码,通用性更强。

    • 效果图:


  • 相关阅读:
    LeetCode15 3Sum
    LeetCode10 Regular Expression Matching
    LeetCode20 Valid Parentheses
    LeetCode21 Merge Two Sorted Lists
    LeetCode13 Roman to Integer
    LeetCode12 Integer to Roman
    LeetCode11 Container With Most Water
    LeetCode19 Remove Nth Node From End of List
    LeetCode14 Longest Common Prefix
    LeetCode9 Palindrome Number
  • 原文地址:https://www.cnblogs.com/guanxinjing/p/9708603.html
Copyright © 2011-2022 走看看