Android动画

作者: 四月一号 | 来源:发表于2016-08-03 12:24 被阅读634次

    Animation


    • Animation类是所有动画(scale、alpha、translate、rotate)的基类,以下是关于 Animation 的属性及意义:
    • android:duration 动画持续时间,以毫秒为单位
    • android:fillAfter 如果设置为true,控件动画结束时,将保持动画最后时的状态
    • android:fillBefore 如果设置为true,控件动画结束时,还原到开始动画前的状态
    • android:fillEnabled 与android:fillBefore 效果相同,都是在动画结束时,将控件还原到初始化状态
    • android:repeatCount 重复次数
    • android:repeatMode 重复类型,有reverse和restart两个值,reverse表示倒序回放,restart表示重新放一遍,必须与repeatCount一起使用才能看到效果。因为这里的意义是重复的类型,即回放时的动作。
    • android:interpolator 设定插值器,其实就是指定的动作效果,比如弹跳效果等
    scale
    • scale标签是缩放动画,可以实现动态调控件尺寸的效果,有下面几个属性:
    • android:fromXScale 起始的X方向上相对自身的缩放比例,浮点值,比如1.0代表自身无变化,0.5代表起始时缩小一倍,2.0代表放大一倍;
    • android:toXScale 结尾的X方向上相对自身的缩放比例,浮点值;
    • android:fromYScale 起始的Y方向上相对自身的缩放比例,浮点值,
    • android:toYScale 结尾的Y方向上相对自身的缩放比例,浮点值;
    • android:pivotX 缩放起点X轴坐标,可以是数值、百分数、百分数p 三种样式,比如 50、50%、50%p,当为数值时,表示在当前View的左上角,即原点处加上50px,做为起始缩放点;如果是50%,表示在当前控件的左上角加上自己宽度的50%做为起始点;如果是50%p,那么就是表示在当前的左上角加上父控件宽度的50%做为起始点x轴坐标。
    • android:pivotY 缩放起点Y轴坐标,取值及意义跟android:pivotX一样。
    alpha
    • alpha是透明动画,调节控件的透明度,属性如下:
    • android:fromAlpha 动画开始的透明度,从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
    • android:toAlpha 动画结束时的透明度,也是从0.0 --1.0 ,0.0表示全透明,1.0表示完全不透明
    rotate
    • rotate是旋转动画,控制控件在平面上的旋转角度
    • android:fromDegrees 开始旋转的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
    • android:toDegrees 结束时旋转到的角度位置,正值代表顺时针方向度数,负值代码逆时针方向度数
    • android:pivotX 旋转中点X坐标
    • android:pivotY 旋转中点Y坐标
    translate
    • translate是平移动画,控制控件水平或垂直移动
    • android:fromXDelta 起始点X轴坐标,可以是数值、百分数、百分数p 三种样式
    • android:fromYDelta 起始点Y轴从标
    • android:toXDelta 结束点X轴坐标
    • android:toYDelta 结束点Y轴坐标
    set
    • set定义动画的集合,可以将多个动画打包执行,在XML中set的定义方式如下:
      <?xml version="1.0" encoding="utf-8"?>
      <set xmlns:android="http://schemas.android.com/apk/res/android"
      android:duration="3000"
      android:fillAfter="true">

           <alpha   
               android:fromAlpha="0.0"  
               android:toAlpha="1.0"/>  
      
           <scale  
               android:fromXScale="0.0"  
               android:toXScale="1.4"  
               android:fromYScale="0.0"  
               android:toYScale="1.4"  
               android:pivotX="50%"  
               android:pivotY="50%"/>  
      
          <rotate  
               android:fromDegrees="0"  
               android:toDegrees="720"  
               android:pivotX="50%"  
              android:pivotY="50%"/>  
         
      </set> 
      
    执行动画(XML)
    • 在项目的 res -> anim下定义动画(xxx.xml)
    • 在代码中加载动画,并让目标控件执行
      Animation anim = AnimationUtils.loadAnimation(this, R.anim.xxx);
      imag.startAnimation(anim);
    Interpolator插值器
    • Interpolator赋予动画一些特性,它指定了动画变化的特征,系统提供的Interpolator如下:
      • AccelerateDecelerateInterpolator 在动画开始与介绍的地方速率改变比较慢,在中间的时候加速
    • AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
    • AnticipateInterpolator 开始的时候向后然后向前甩
    • AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
    • BounceInterpolator 动画结束的时候弹起
    • CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
    • DecelerateInterpolator 在动画开始的地方快然后慢
    • LinearInterpolator 以常量速率改变
    • OvershootInterpolator 向前甩一定值后再回到原来位置
    • xml动画中添加Interpolator
      android:interpolator="@android:anim/accelerate_decelerate_interpolator"
    代码生成动画

    前面介绍了通过xml定义动画,动画集合,插值器等,其实通过代码也可以做到.

    • ScaleAnimation
      ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
      scaleAnim.setDuration(700);

      //它相当于在xml如下定义
       <?xml version="1.0" encoding="utf-8"?>  
       <scale xmlns:android="http://schemas.android.com/apk/res/android"                                                                   
           android:fromXScale="0.0"  
           android:toXScale="1.4"  
           android:fromYScale="0.0"  
           android:toYScale="1.4"  
           android:pivotX="50"  
           android:pivotY="50"  
           android:duration="700" />    
      
    • AlphaAnimation
      AlphaAnimation alphaAnim = new AlphaAnimation(1.0f,0.1f);
      alphaAnim.setDuration(3000);
      alphaAnim.setFillBefore(true);

      //对应xml属性如下:
      //android:fromAlpha="1.0"  
      //android:toAlpha="0.1"  
      //android:duration="3000"  
      //android:fillBefore="true"    
      
    • RotateAnimation
      RotateAnimation rotateAnim = new RotateAnimation(0, -650, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
      rotateAnim.setDuration(3000);
      rotateAnim.setFillAfter(true);

      //对应xml属性如下:
      //android:fromDegrees="0"  
      //android:toDegrees="-650"  
      //android:pivotX="50%"  
      //android:pivotY="50%"  
      //android:duration="3000"  
      //android:fillAfter="true"
      
    • TranslateAnimation
      TranslateAnimation translateAnim = new TranslateAnimation(Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80,
      Animation.ABSOLUTE, 0, Animation.ABSOLUTE, -80);
      translateAnim.setDuration(2000);
      translateAnim.setFillBefore(true);

      //对应xml属性:
      //android:fromXDelta="0"   
      //android:toXDelta="-80"  
      //android:fromYDelta="0"  
      //android:toYDelta="-80"  
      //android:duration="2000"  
      //android:fillBefore="true"
      
    • AnimationSet
      AlphaAnimation alphaAnim = new AlphaAnimation(1.0f,0.1f);
      ScaleAnimation scaleAnim = new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
      RotateAnimation rotateAnim = new RotateAnimation(0, 720, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);

      AnimationSet setAnim=new AnimationSet(true);  
      setAnim.addAnimation(alphaAnim);  
      setAnim.addAnimation(scaleAnim);  
      setAnim.addAnimation(rotateAnim);   
      setAnim.setDuration(3000);  
      
    • Interpolater
      ScaleAnimation interpolateScaleAnim=new ScaleAnimation(0.0f,1.4f,0.0f,1.4f,Animation.RELATIVE_TO_SELF,0.5f,Animation.RELATIVE_TO_SELF,0.5f);
      interpolateScaleAnim.setInterpolator(new BounceInterpolator());
      interpolateScaleAnim.setDuration(3000);

    Property Animator(属性动画)


    ValueAnimator
    • ValueAnimator只负责对指定的数字区间进行动画运算

    • 我们需要对运算过程进行监听,然后自己对控件做动画操作

    • ValueAnimator的构件方法
      public static ValueAnimator ofInt(int... values)
      public static ValueAnimator ofFloat(float... values)

       //他们的参数类型都是可变参数长参数,所以我们可以传入任何数量的值;传进去的值列表,就表示动画时的变化范围;
       //比如ofInt(2,90,45)就表示从数值2变化到数字90再变化到数字45;所以我们传进去的数字越多,动画变化就越复杂。
       //从参数类型也可以看出ofInt与ofFloat的唯一区别就是传入的数字类型不一样,
       //ofInt需要传入Int类型的参数,而ofFloat则表示需要传入Float类型的参数。 
      
    • ValueAnimator的常用函数
      //设置动画时长,单位是毫秒
      ValueAnimator setDuration(long duration)
      //获取ValueAnimator在运动时,当前运动点的值
      Object getAnimatedValue();
      //开始动画
      void start()
      //设置循环次数,设置为INFINITE表示无限循环
      void setRepeatCount(int value)
      //设置循环模式 value取值有RESTART,REVERSE,
      void setRepeatMode(int value)
      //取消动画
      void cancel()
      //设置插值器
      void setInterpolator(TimeInterpolator value)
      //延时多久时间开始,单位是毫秒
      void setStartDelay(long startDelay)
      //完全克隆一个ValueAnimator实例,包括它所有的设置以及所有对监听器代码的处理
      ValueAnimator clone()

    • 举例说明ValueAnimator的使用方式
      ValueAnimator animator = ValueAnimator.ofFloat(0f,400f,50f,300f);
      animator.setDuration(3000);
      //监听动画变化时的实时值
      animator.addUpdateListener(
      new ValueAnimator.AnimatorUpdateListener() {
      @Override
      public void onAnimationUpdate(ValueAnimator animation) {
      //获取当前的值(这里传入的是float,所以强转为Float)
      Float curValueFloat = (Float)animation.getAnimatedValue();
      int curValue = curValueFloat.intValue();
      //跟随值的变化,而改变控件的属性
      tv.layout(curValue,curValue,curValue+tv.getWidth(),
      curValue+tv.getHeight());
      }
      });
      animator.start();

    • ValueAnimator 监听
      /**
      * 监听器一:监听动画变化时的实时值
      */
      public static interface AnimatorUpdateListener {
      void onAnimationUpdate(ValueAnimator animation);
      }
      //添加方法为:
      //public void addUpdateListener(AnimatorUpdateListener listener)
      //移除的方法
      //void removeUpdateListener(AnimatorUpdateListener listener);
      //void removeAllUpdateListeners();

      /** 
       * 监听器二:监听动画变化时四个状态 
       */  
       public static interface AnimatorListener {  
         void onAnimationStart(Animator animation);  
         void onAnimationEnd(Animator animation);  
         void onAnimationCancel(Animator animation);  
         void onAnimationRepeat(Animator animation);  
      }  
      //添加方法为:
      //public void addListener(AnimatorListener listener)  
      //void removeListener(AnimatorListener listener);  
      //void removeAllListeners(); 
      
    • 自定义Interpolator
      public class MyInterpolator implements Interpolator {

         public LinearInterpolator() {  
         }  
      
         public LinearInterpolator(Context context, AttributeSet attrs) {  
         }  
      
         public float getInterpolation(float input) { 
            // input表示动画的时间进度,范围是0到1,随着动画的执行匀速增长
            // 返回值表示动画的实际进度,是关于input的一维函数
            // 当前的值 = start + (end- start)* 动画进度
            return input;  
         }  
      }  
      
    • Evaluator

      • 插值器的进度,是如何转换为动画实际的值?
        Evaluator就是将动画进度转换为实际值的东西,它定义了转换的规则.
      • FloatEvaluator 和 IntEvaluator分别对应 ofFloat() 和 ofInt()
        当我们定义动画的时候,如果不显示的添加Evaluator,则使用默认的Evaluator
        public class IntEvaluator implements TypeEvaluator<Integer> {
        public Integer evaluate(float fraction,
        Integer startValue, Integer endValue) {
        int startInt = startValue;
        //当前的值 = start + (end- start)* 动画进度
        //可以自定义规则
        return (int)(startInt + fraction * (endValue - startInt));
        }
        }
    • ArgbEvaluator (用于处理颜色值过渡转换)
      public class ArgbEvaluator implements TypeEvaluator {
      public Object evaluate(float fraction,
      Object startValue, Object endValue) {
      int startInt = (Integer) startValue;
      int startA = (startInt >> 24);
      int startR = (startInt >> 16) & 0xff;
      int startG = (startInt >> 8) & 0xff;
      int startB = startInt & 0xff;

              int endInt = (Integer) endValue;  
              int endA = (endInt >> 24);  
              int endR = (endInt >> 16) & 0xff;  
              int endG = (endInt >> 8) & 0xff;  
              int endB = endInt & 0xff;  
      
              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))));  
            }  
       }  
      
       ...
       //使用例子
        ValueAnimator animator = ValueAnimator.ofInt(0xffffff00,0xff0000ff);                                                                    
        animator.setEvaluator(new ArgbEvaluator());  
        animator.setDuration(3000);  
      
        animator.addUpdateListener(
                new ValueAnimator.AnimatorUpdateListener() {  
           @Override  
           public void onAnimationUpdate(ValueAnimator animation) {  
               int curValue = (int)animation.getAnimatedValue();  
               tv.setBackgroundColor(curValue);  
           }  
        });  
        animator.start();  
      
    • ofObject()
      public static ValueAnimator ofObject(TypeEvaluator evaluator, Object... values);
      //ofObject相对于ofInt和ofFloat自由度更大些,相应也更复杂点.个人认为ofObject使用的机会不多,所以简单列举一个例子说明它的用法

        ValueAnimator animator = ValueAnimator.ofObject(new CharEvaluator(),new Character('A'),new Character('Z'));                                                                                    
        animator.addUpdateListener(
                new ValueAnimator.AnimatorUpdateListener() {  
          @Override  
          public void onAnimationUpdate(ValueAnimator animation) {  
                 char text = (char)animation.getAnimatedValue();  
                tv.setText(String.valueOf(text));  
          }  
        });  
        animator.setDuration(10000);  
        animator.setInterpolator(new AccelerateInterpolator());  
        animator.start();  
      
        //... 自定义Evaluator
        
        public class CharEvaluator implements TypeEvaluator<Character> {  
             @Override  
             public Character evaluate(float fraction,
                          Character startValue, Character endValue) {  
                  int startInt  = (int)startValue;  
                  int endInt = (int)endValue;  
                  int curInt = (int)(startInt + fraction *(endInt - startInt));  
                  char result = (char)curInt;  
                  return result;  
              }  
         }  
      
    ObjectAnimator
    • ValueAnimator使用相对比较麻烦,谷歌在ValueAnimator的基础上派生了ObjectAnimator,所以ObjectAnimator可以视为ValueAnimator的封装,使用起来更简单.
      public static ObjectAnimator ofInt(Object target, String propertyName, int... values)
      public static ObjectAnimator ofFloat(Object target, String propertyName, float... values)

       ...
       //以下是透明,旋转,位移,缩放动画的定义
       ObjectAnimator animator =  ObjectAnimator.ofFloat(tv,"alpha",1,0,1);  
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotation",0,180,0);   
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationX",0,270,0);
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv,"rotationY",0,180,0);
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationX", 0, 200,-200,0);
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "translationY", 0, 200,-100,0);
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleX", 0, 3, 1); 
       ObjectAnimator animator = ObjectAnimator.ofFloat(tv, "scaleY", 0, 3, 1);
      
    • why ? 为什么通过一段字符串,就可以执行指定的动画?

      • 其实上面这些属性,都有其对应的set函数:
        • setAlpha()
        • setRotation() / setRotationY() / setRotationX()
        • setTranslationY() / setTranslationX()
        • setScaleX() / setScaleY()
          当我们使用以上方式定义属性动画时,系统会拼接出目标控件对应的set函数,然后通过反射执行.
          依次类推,只要控件有某一set函数,我们就可以定义对应的动画,比如:
          //setBackgrounColor()
          ObjectAnimator animator = ObjectAnimator.ofInt(tv, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
          animator.setDuration(8000);
          animator.setEvaluator(new ArgbEvaluator());
          animator.start();
          进一步,自定义控件的时候,我们可以自定义set函数,都可以使用对应的动画
    • 因为ObjectAnimator派生自ValueAnimator,所以ValueAnimator其它的函数,它都可以使用,这里不再叙述

    • 属性的get函数又有何作用呢 ?
      我们已经知道属性的set函数的作用,那么对应的get函数有没有什么特殊的作用呢?
      有,OberjectAnimator的构件方法,所需的值都是可变参数,如果只传入一个值呢?动画该怎么执行?
      当只有一个值的时候,这个值将是动画的结束值,而开始值,则由相应的get函数返回

    • PropertyValuesHolder
      PropertyValuesHolder也可以用来构造动画,事实上,前面我们讲的动画的构造,最终都是通过PropertyValuesHolder完成,并且PropertyValuesHolder可以让多个动画效果一起执行,先看下几个系统的函数:
      // ObjectAnimator
      public static ObjectAnimator ofPropertyValuesHolder(Object target,PropertyValuesHolder... values)
      // 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)

      // 其实已经很明显了,我们可以使用PropertyValuesHolder 构建具体的动画效果, 
      //然后使用 ObjectAnimator 的 ofPropertyValuesHolder函数将一个或多个PropertyValuesHolder 打包创建为动画对象
      //以下是 使用PropertyValuesHolder 创建动画的例子:
      PropertyValuesHolder rotationHolder = PropertyValuesHolder.ofFloat("Rotation", 60f, -60f, 40f, -40f, -20f, 20f, 10f, -10f, 0f);  
      PropertyValuesHolder colorHolder = PropertyValuesHolder.ofInt("BackgroundColor", 0xffffffff, 0xffff00ff, 0xffffff00, 0xffffffff);  
      ObjectAnimator animator = ObjectAnimator.ofPropertyValuesHolder(mTextView, rotationHolder, colorHolder);  
      animator.setDuration(3000);  
      animator.setInterpolator(new AccelerateInterpolator());  
      animator.start(); 
      
      //关于ofObject的使用方与ObjectAnimator的ofObject大同小异...
      //ofKeyframe会在下面具体讲解
      
    • Keyframe(关键帧)
      之前我们知道,通过插值器和Evaluator可以控制动画的变化速率,但如果要实现更复杂的效果,就需要定义更复杂的公式.Keyframe同样可以控制动画的速率,使用起来也更简单.在讲自定义插值器的时候,曾提到过,动画的进度在0~1之间,而Keyframe可以让我们指定动画在某一进度点上的值,通过这种方式,我们可以更灵活,更简单的控制动画的速率.
      //动画开始的值为 0
      Keyframe frame0 = Keyframe.ofFloat(0f, 0);
      //动画进度为0.1的时候,值为 -20
      Keyframe frame1 = Keyframe.ofFloat(0.1f, -20f);
      //动画结束的时候,值为 0
      Keyframe frame2 = Keyframe.ofFloat(1, 0);
      //通过 Keyframe 构建 PropertyValuesHolder
      PropertyValuesHolder frameHolder = PropertyValuesHolder.ofKeyframe("rotation",frame0,frame1,frame2);
      Animator animator = ObjectAnimator.ofPropertyValuesHolder(mImage,frameHolder);
      animator.setDuration(1000);
      animator.start();

      //使用Keyframe,每两帧之间默认匀速执行,即线性插值器,更强大的是,我们可以给Keyframe指定插值器,
      //如果给某个Keyframe设置了插值器,那么从前一帧到这一帧的动画会按插值器执行
      public void setInterpolator(TimeInterpolator interpolator)
      
      //同样的,Keyframe的构建方式也有以下几种
      public static Keyframe ofInt(float fraction, int value)  
      public static Keyframe ofFloat(float fraction, float value)
      public static Keyframe ofObject(float fraction, Object value)
      
      //***需要强调的是,使用Keyframe的时候,最少需要两帧,否则会报错
      //***另外第一帧是动画的开始,最后一帧是动画的结束
      
    • AnimatorSet
      顾名思义,AnimatorSet可以联合多个动画一起执行:
      //多个动画顺序执行
      public void playSequentially(Animator... items);
      public void playSequentially(List<Animator> items);
      //多个动画同时执行
      public void playTogether(Animator... items);
      public void playTogether(Collection<Animator> items);

      //以上方式都比较简单, 我们可以使用AnimatorSet.Builder实现更具体的控制,比如指定动画的执行顺序
      // 执行动画
      public Builder after(Animator aim)
      //和前面动画一起执行
      public Builder with(Animator anim)
      //先执行前面的动画,再执行这个动画
      public Builder before(Animator anim)
      //先执行这个动画,再执行前面的动画
      public Builder after(Animator anim)
      
      //示例如下
      ObjectAnimator tv1BgAnimator = ObjectAnimator.ofInt(mTv1, "BackgroundColor", 0xffff00ff, 0xffffff00, 0xffff00ff);
      ObjectAnimator tv1TranslateY = ObjectAnimator.ofFloat(mTv1, "translationY", 0, 400, 0);
      ObjectAnimator tv2TranslateY = ObjectAnimator.ofFloat(mTv2, "translationY", 0, 400, 0);
      AnimatorSet animatorSet = new AnimatorSet();
      animatorSet.play(tv1TranslateY).with(tv2TranslateY).after(tv1BgAnimator);
      animatorSet.setDuration(2000);
      animatorSet.start();
      
    • AnimatorSet 可以通过*addListener(AnimatorListener listener) *监听其状态的变化

    • 需要注意的是,某些属性可以通过AnimatorSet统一设置,比如: 动画时长,重复次数等.并且如果统一设置了这些属性,那么针对单个动画的设置将无效.

    • 使用XML定义属性动画

      • 在xml中对应animator总共有三个标签,分别是

    <animator /> 对应ValueAnimator
    <objectAnimator /> 对应ObjectAnimator
    <set /> 对应AnimatorSet

    • animator (以下是animator完整的字段,及对应的值类型)
      <animator android:duration="int"
      android:valueFrom="float | int | color"
      android:valueTo="float | int | color"
      android:startOffset="int"
      android:repeatCount="int"
      android:repeatMode=["repeat" | "reverse"]
      android:valueType=["intType" | "floatType"]
      android:interpolator=["@android:interpolator/XXX"]/>

      • android:duration:每次动画播放的时长
      • android:valueFrom:初始动化值;取值范围为float,int和color,如果取值为float对应的值样式应该为89.0,取值为Int时,对应的值样式为:89;当取值为clolor时,对应的值样式为 #333333;
      • android:valueTo:动画结束值;取值范围同样是float,int和color这三种类型的值;
      • android:startOffset:动画激活延时;对应代码中的startDelay(long delay)函数;
      • android:repeatCount:动画重复次数
      • android:repeatMode:动画重复模式,取值为repeat和reverse;repeat表示正序重播,reverse表示倒序重播
      • android:valueType:表示参数值类型,取值为intType和floatType;与android:valueFrom、android:valueTo相对应。如果这里的取值为intType,那么android:valueFrom、android:valueTo的值也就要对应的是int类型的数值。如果这里的数值是floatType,那么android:valueFrom、android:valueTo的值也要对应的设置为float类型的值。非常注意的是,如果android:valueFrom、android:valueTo的值设置为color类型的值,那么不需要设置这个参数;
      • android:interpolator:设置加速器
    • objectAnimator
      objectAnimator对比animator多了一条属性
      android:propertyName="string"

      • android:propertyName:对应属性名,即ObjectAnimator所需要操作的属性名
    • set(set标签只有一条属性)
      <set android:ordering=["together" | "sequentially"]>

      • android:ordering:表示动画开始顺序。together表示同时开始动画,sequentially表示逐个开始动画
    • 加载XML里定义的动画
      ValueAnimator valueAnimator = (ValueAnimator) AnimatorInflater.loadAnimator(context,R.animator.animator);
      valueAnimator.start();

       ObjectAnimator animator = (ObjectAnimator) AnimatorInflater.loadAnimator(MyActivity.this, R.animator.object_animator);
       animator.setTarget(mTv1);
       animator.start();
      
       AnimatorSet set = (AnimatorSet) AnimatorInflater.loadAnimator(MyActivity.this, R.animator.set_animator);
       set.setTarget(mTv1);
       set.start();
      
    布局动画

    LayoutAnimation
    1. XML实现
      <?xml version="1.0" encoding="utf-8"?>
      <layoutAnimation
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:delay="1"
      android:animationOrder="normal"
      android:animation="@anim/slide_in_left"/>

      ...
      
      <ListView android:id="@+id/listview" 
              android:layout_width="match_parent" 
              android:layout_height="match_parent" 
              android:layoutAnimation="@anim/layout_animation" />
      
    2. 代码实现
      //得到一个LayoutAnimationController对象;
      LayoutAnimationController controller = new LayoutAnimationController(animation);
      //设置控件显示的顺序;
      controller.setOrder(LayoutAnimationController.ORDER_REVERSE);
      //设置控件显示间隔时间;
      controller.setDelay(0.3f);
      //为ListView设置LayoutAnimationController属性;
      mListView.setLayoutAnimation(controller);
      mListView.startLayoutAnimation();

    3. 各字段解释
      delay:指每个Item的动画开始延时,取值是android:animation所指定动画时长的倍数,取值类型可以是float类型,也可以是百分数,默认是0.5;比如我们这里指定的动画是@anim/slide_in_left,而在slide_in_left.xml中指定android:duration=”1000”,即单次动画的时长是1000毫秒,而我们在这里的指定android:delay=”1”,即一个Item的动画会在上一个item动画完成后延时单次动画时长的一倍时间开始,即延时1000毫秒后开始。
      animationOrder:指viewGroup中的控件动画开始顺序,取值有normal(正序)、reverse(倒序)、random(随机)
      animation:指定每个item入场所要应用的动画。仅能指定res/aim文件夹下的animation定义的动画,不可使用animator动画。

    GridLayoutAnimation
    1. XML实现
      <?xml version="1.0" encoding="utf-8"?>
      <gridLayoutAnimation
      xmlns:android="http://schemas.android.com/apk/res/android"
      android:rowDelay="75%"
      android:columnDelay="60%"
      android:directionPriority="none"
      android:direction="bottom_to_top|right_to_left"
      android:animation="@android:anim/slide_in_left"/>

      ***
      
      <GridView android:id="@+id/grid" 
            android:layout_width="match_parent" 
            android:layout_height="match_parent" 
            android:columnWidth="60dp" 
            android:gravity="center" 
            android:horizontalSpacing="10dp"           
            android:layoutAnimation="@anim/gride_animation"  
            android:numColumns="auto_fit" 
            android:stretchMode="columnWidth" 
            android:verticalSpacing="10dp"/>
      
    2. 代码实现
      GridLayoutAnimationController controller = new GridLayoutAnimationController(animation);
      controller.setColumnDelay(0.75f);
      controller.setRowDelay(0.5f);
      controller.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP|GridLayoutAnimationController.DIRECTION_LEFT_TO_RIGHT);
      controller.setDirectionPriority(GridLayoutAnimationController.PRIORITY_NONE);
      grid.setLayoutAnimation(controller);
      grid.startLayoutAnimation();

    3. 各属性解释
      rowDelay:每一行动画开始的延迟。与LayoutAnimation一样,可以取百分数,也可以取浮点数。取值意义为,当前android:animation所指动画时长的倍数。 columnDelay:每一列动画开始的延迟。取值类型及意义与rowDelay相同。 directionPriority:方向优先级。取值为row,collumn,none,意义分别为:行优先,列优先,和无优先级(同时进行);
      direction:gridview动画方向。 取值有四个:
      *left_to_right:列,从左向右开始动画
      right_to_left :列,从右向左开始动画
      top_to_bottom:行,从上向下开始动画
      bottom_to_top:行,从下向上开始动画 *
      这四个值之间可以通过“|”连接,从而可以取多个值。
      很显然left_to_right和right_to_left是互斥的,
      top_to_bottom和bottom_to_top是互斥的。
      如果不指定 direction字段,
      默认值为left_to_right | top_to_bottom;
      即从上往下,从左往右。
      animation: gridview内部元素所使用的动画。

    布局增加/移除动画
    1. android:animateLayoutChanges="true"
      只要给布局添加该属性,它内部的控件在添加和删除时,是会带有默认动画
    2. LayoutTransaction ,允许我们自定义动画效果
      LayoutTransaction transitioner = new LayoutTransition();
      ObjectAnimator animOut = ObjectAnimator.ofFloat(null, "rotation", 0f, 90f, 0f);
      //设置动画
      //第一个参数int transitionType:表示当前应用动画的对象范围,取值有:
      //APPEARING —— 添加元素的动画
      //DISAPPEARING —— 移除元素的动画
      //CHANGE_APPEARING —— 添加元素时,其它元素的动画(该动画必须通过PropertyValuesHolder创建)
      //CHANGE_DISAPPEARING —— 移除元素时,其它元素的动画(该动画必须通过PropertyValuesHolder创建)
      //第二个参数Animator animator:表示当前所选范围的控件所使用的动画。
      transitioner.setAnimator(LayoutTransition.DISAPPEARING, animOut);
      //将LayoutTransaction设置进ViewGroup
      linearLayout.setLayoutTransition(mTransitioner);
      因为LayoutTransaction 使用的机会不多,且实际应用相对麻烦,所以不再详细说明

    相关文章

      网友评论

        本文标题:Android动画

        本文链接:https://www.haomeiwen.com/subject/gabfsttx.html