A09_Android动画

来源:互联网 发布:无限发短信软件 编辑:程序博客网 时间:2024/06/04 14:58

帧动画FrameAnimation

胶片电影,早期的动画–多张图片快速切换形成动画效果,主要应用在读取界面

帧动画使用XML定义

<?xml version="1.0" encoding="utf-8"?><animation-list xmlns:android="http://schemas.android.com/apk/res/android"    android:oneshot="false">    <item android:drawable="@drawable/g1" android:duration="200" />    <item android:drawable="@drawable/g2" android:duration="200" />    <item android:drawable="@drawable/g3" android:duration="200" />    <item android:drawable="@drawable/g4" android:duration="200" />    <item android:drawable="@drawable/g5" android:duration="200" />    <item android:drawable="@drawable/g6" android:duration="300" />    <item android:drawable="@drawable/g7" android:duration="300" />    <item android:drawable="@drawable/g8" android:duration="300" />    <item android:drawable="@drawable/g9" android:duration="200" />    <item android:drawable="@drawable/g10" android:duration="200" />    <item android:drawable="@drawable/g11" android:duration="200" /></animation-list>

在Activity代码中

ImageView iv = (ImageView) findViewById(R.id.iv);iv.setBackgroundResource(R.drawable.frameanimation);AnimationDrawable ad = (AnimationDrawable)iv.getBackground();ad.start();

补间动画ViewAnimation

组件由原始状态向终极状态转变时,为了让过渡更自然,而自动生成的动画

位移动画TranslateAnimation

TranslateAnimation ta=new TranslateAnimation(10,100,20,100);
  • 10:表示x坐标起始位置,不是绝对坐标,是相对的,组件的绝对x+10,下同
  • 100:表示x坐标的结束位置
  • 20:表示y坐标起始位置
  • 100:表示y坐标的结束位置

另一种

ta = new TranslateAnimation(    Animation.RELATIVE_TO_SELF, 1,     Animation.RELATIVE_TO_SELF, 2,    Animation.RELATIVE_TO_SELF, -0.5f,     Animation.RELATIVE_TO_SELF, 1.5f);  

Animation.RELATIVE_TO_SELF, 1:组件的绝对x坐标+1×组件的宽

//平移动画//      TranslateAnimation ta=new TranslateAnimation(0, 50, 0, 50);        //相对自己=RELATIVE_TO_SELF,0=控件绝对X+控件宽度*0        //相对父容器=RELATIVE_TO_PARENT,0=控件绝对X+父容器宽度*0        TranslateAnimation ta=new TranslateAnimation(Animation.RELATIVE_TO_PARENT,-1,                 Animation.RELATIVE_TO_PARENT, 2,                 Animation.RELATIVE_TO_PARENT, -1,                 Animation.RELATIVE_TO_PARENT, 2);        //设置播放时间        ta.setDuration(1000);        //设置重复次数        ta.setRepeatCount(3);        //重复模式,默认从头重复        ta.setRepeatMode(Animation.REVERSE);        iv.startAnimation(ta);

缩放动画ScaleAnimation

        //缩放动画    //缩放点在左上角//      ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5);        //后两个参数代表缩放的中心点,默认控件左上角//      ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5, iv.getWidth()/2, iv.getHeight()/2);        ScaleAnimation sa=new ScaleAnimation(1, 5, 1, 5,                 Animation.RELATIVE_TO_SELF, 0.5f,                 Animation.RELATIVE_TO_SELF, 0.5f);        sa.setDuration(2000);        sa.setRepeatCount(1);        sa.setRepeatMode(Animation.REVERSE);        //填充动画的结束位置        sa.setFillAfter(true);        iv.startAnimation(sa);

透明动画AlphaAnimation

    //透明度动画    //起始透明度-结束透明度 0-1     AlphaAnimation aa=new AlphaAnimation(0.1f, 1);    aa.setDuration(2000);    iv.startAnimation(aa);

旋转动画RotateAnimation

//旋转动画    //以左上角为中心,旋转0-360度//      RotateAnimation ra=new RotateAnimation(0, 720);//      RotateAnimation ra=new RotateAnimation(0, 360, iv.getWidth()/2, iv.getHeight()/2);        RotateAnimation ra=new RotateAnimation(0, 180,                 Animation.RELATIVE_TO_SELF, 0.5f,                 Animation.RELATIVE_TO_SELF, 0.5f);        ra.setDuration(2000);        ra.setRepeatCount(2);        ra.setRepeatMode(Animation.REVERSE);        ra.setFillAfter(true);        iv.startAnimation(ra);

动画集AnimationSet

将以上四种动画合为一体

注:点击报错,因为空指针,没有对所设置的动画进行初始化

    AnimationSet set=new AnimationSet(false);    set.addAnimation(ta);    set.addAnimation(sa);    set.addAnimation(aa);    set.addAnimation(ra);    iv.startAnimation(set);

属性动画PropertyAnimation

补间动画仅仅改变的是控件在界面上的绘制效果,但实质位置还在原处。

既然是属性动画,所以我们最终操作的属性的改变,在这里,属性需要符合bean规范,大部分控件的setter方法会重绘组件。

平移

这里的ObjectAnimator中只能一次改变一个属性

且,iv.setTranslationX(translationX);中translationX符合并规范,于是平移代码如下

    //参数1:哪个控件要执行动画    //参数2:要改变哪个属性    //参数3:改变的过程,左负右正(相对控件本身的坐标点)    //这里指,iv的x坐标先从自身(0),移动到100,再移动到50,再移动到150,最后回归    oa1 = ObjectAnimator.ofFloat(iv, "translationX", 0,100,50,150,0);    oa1.setDuration(2000);    oa1.setRepeatCount(1);    oa1.start();

缩放

    oa2 = ObjectAnimator.ofFloat(iv,"scaleX",1,2,1,3,4);    oa2.setDuration(2000);    oa2.start();

透明度

    oa3 = ObjectAnimator.ofFloat(iv,"alpha",1,0.5f,1,0.3f,1,0,1);    oa3.setDuration(2000);    oa3.start();

旋转

    oa4 = ObjectAnimator.ofFloat(iv,"rotation",0,180,-180,180);    oa4.setDuration(2000);    oa4.setRepeatCount(1);    oa4.start();

动画集合AnimatorSet

    AnimatorSet set=new AnimatorSet();    //按顺序执行    //set.playSequentially(items);    //一起执行    set.playTogether(oa1,oa2,oa3,oa4);    set.start();

如果所操作的对象的属性方法里,没有调用view的重绘,则需要自己按照下面方式手动调用。

    oa1.addUpdateListener(new AnimatorUpdateListener()      {          @Override          public void onAnimationUpdate(ValueAnimator animation)          {              //view.postInvalidate();              //view.invalidate();          }      }); 

如果要执行多种动画,如下代码:

  • 依据addUpdateListener

    //2.依照addUpdateListener实现多动画实现ObjectAnimator anim=ObjectAnimator.ofFloat(iv, "abc", 1.0f,0.0f,1.0f).setDuration(1000);anim.start();anim.addUpdateListener(new AnimatorUpdateListener() {    @Override    public void onAnimationUpdate(ValueAnimator animation) {    float val=(Float) animation.getAnimatedValue();    iv.setAlpha(val);    iv.setScaleX(val);    iv.setScaleY(val);    iv.setTranslationX(val);    iv.setTranslationY(val);    }});
  • 依据PropertyValuesHolder

    //3.依据PropertyValuesHolder实现多动画处理PropertyValuesHolder pvh1=PropertyValuesHolder.ofFloat("alpha", 1.0f,0.1f,1.0f);PropertyValuesHolder pvh2=PropertyValuesHolder.ofFloat("scaleX", 1,2,1);PropertyValuesHolder pvh3=PropertyValuesHolder.ofFloat("scaleY", 1,2,1);PropertyValuesHolder pvh4=PropertyValuesHolder.ofFloat("translationX", 0,150,0);ObjectAnimator.ofPropertyValuesHolder(iv,pvh1,pvh2,pvh3,pvh4).setDuration(2000).start();

属性动画深入解析

属性动画的出现,解决了补间动画的三种问题

  • 解决了补间动画不能对非View进行动画的问题
  • 解决了补间动画不能实现颜色背景动画等特殊动画的问题
  • 解决了补间动画只是View的显示效果的缺陷

ValueAnimator

核心类

属性动画的运行机制是通过不断地对值进行操作来实现的,而初始值和结束值之间的动画过渡就是由ValueAnimator这个类来负责计算的。它的内部使用一种时间循环的机制来计算值与值之间的动画过渡,我们只需要将初始值和结束值提供给ValueAnimator,并且告诉它动画所需运行的时长,那么ValueAnimator就会自动帮我们完成从初始值平滑地过渡到结束值的效果。除此之外,ValueAnimator还负责管理动画的播放次数、播放模式、以及对动画设置监听器等。

比如将一个值从0平滑过渡到1,时长300毫秒,

ValueAnimator anim=ValueAnimator.ofFloat(0f,1f);anim.setDuration(300);anim.start();

运行代码,动画就会执行,但这样并没有任何界面效果,如何得知动画是否运行,就需要设置一个监听器

anim.addUpdateListener(new AnimatorUpdateListener() {        @Override        public void onAnimationUpdate(ValueAnimator animation) {            float cVal=(Float) animation.getAnimatedValue();            Log.d("TAG", "current vlaue is "+cVal);        }    });

日志结果如下:

  • 07-25 06:27:58.440: D/TAG(4914): current vlaue is 0.0
  • 07-25 06:27:58.460: D/TAG(4914): current vlaue is 0.0070019662
  • 07-25 06:27:58.472: D/TAG(4914): current vlaue is 0.029559612
  • 07-25 06:27:58.492: D/TAG(4914): current vlaue is 0.066987276
  • 07-25 06:27:58.508: D/TAG(4914): current vlaue is 0.11474341
  • 07-25 06:27:58.524: D/TAG(4914): current vlaue is 0.17727113
  • 07-25 06:27:58.544: D/TAG(4914): current vlaue is 0.25000006
  • 07-25 06:27:58.560: D/TAG(4914): current vlaue is 0.32571396
  • 07-25 06:27:58.576: D/TAG(4914): current vlaue is 0.41145772
  • 07-25 06:27:58.592: D/TAG(4914): current vlaue is 0.5
  • 07-25 06:27:58.608: D/TAG(4914): current vlaue is 0.5833843
  • 07-25 06:27:58.624: D/TAG(4914): current vlaue is 0.669369
  • 07-25 06:27:58.644: D/TAG(4914): current vlaue is 0.7500001
  • 07-25 06:27:58.656: D/TAG(4914): current vlaue is 0.818712
  • 07-25 06:27:58.672: D/TAG(4914): current vlaue is 0.881898
  • 07-25 06:27:58.692: D/TAG(4914): current vlaue is 0.9330126
  • 07-25 06:27:58.708: D/TAG(4914): current vlaue is 0.968641
  • 07-25 06:27:58.724: D/TAG(4914): current vlaue is 0.99209785
  • 07-25 06:27:58.740: D/TAG(4914): current vlaue is 1.0

ObjectAnimator

常用类

ValueAnimator只不过是对值进行了一个平滑的动画过渡,而ObjectAnimator则就不同了,它是可以直接对任意对象的任意属性进行动画操作的。

但是ObjectAnimator是继承自ValueAnimator的,底层的动画实现机制也是基于ValueAnimator的。

    ObjectAnimator moveIn = ObjectAnimator.ofFloat(tv, "translationX", -400f, 0f);      ObjectAnimator rotate = ObjectAnimator.ofFloat(tv, "rotation", 0f, 360f);      ObjectAnimator fadeInOut = ObjectAnimator.ofFloat(tv, "alpha", 1f, 0f, 1f);      AnimatorSet animSet=new AnimatorSet();    animSet.play(rotate).with(fadeInOut).after(moveIn);    animSet.setDuration(5000);    animSet.start();

Animator监听器

只要继承了Animator,都可包含该方法和监听器

在很多时候,我们希望可以监听到动画的各种事件,比如动画何时开始,何时结束,然后在开始或者结束的时候去执行一些逻辑处理。这个功能是完全可以实现的,Animator类当中提供了一个addListener()方法,这个方法接收一个AnimatorListener,我们只需要去实现这个AnimatorListener就可以监听动画的各种事件了。

animSet.addListener(new AnimatorListener() {        @Override        public void onAnimationStart(Animator animation) {            // TODO Auto-generated method stub        }        @Override        public void onAnimationRepeat(Animator animation) {            // TODO Auto-generated method stub        }        @Override        public void onAnimationEnd(Animator animation) {            // TODO Auto-generated method stub        }        @Override        public void onAnimationCancel(Animator animation) {            // TODO Auto-generated method stub        }    });
  • onAnimationStart()方法会在动画开始的时候调用
  • onAnimationRepeat()方法会在动画重复执行的时候调用
  • onAnimationEnd()方法会在动画结束的时候调用
  • onAnimationCancel()方法会在动画被取消的时候调用

也可监听某一动画事件,AnimatorListenerAdapter

animSet.addListener(new AnimatorListenerAdapter() {        @Override        public void onAnimationEnd(Animator animation) {            // TODO Auto-generated method stub            super.onAnimationEnd(animation);        }    });

TypeEvaluator的高级用法

TypeEvaluator的作用是什么,就是告诉动画系统如何从初始值过渡到结束值。在ValueAnimator.ofFloat()中就实现了初始值与结束值之间的平滑过渡,那么这个平滑过渡是怎么做到的呢?其实就是系统内置了一个FloatEvaluator,它通过计算告知动画系统如何从初始值过渡到结束值,我们来看一下FloatEvaluator的代码实现:

    public class FloatEvaluator implements TypeEvaluator {          public Object evaluate(float fraction, Object startValue, Object endValue) {              float startFloat = ((Number) startValue).floatValue();              return startFloat + fraction * (((Number) endValue).floatValue() - startFloat);          }      }  

evaluate()方法当中传入了三个参数,第一个参数fraction非常重要,这个参数用于表示动画的完成度的,我们应该根据它来计算当前动画的值应该是多少,第二第三个参数分别表示动画的初始值和结束值。那么上述代码的逻辑就比较清晰了,用结束值减去初始值,算出它们之间的差值,然后乘以fraction这个系数,再加上初始值,那么就得到当前动画的值了。

ValueAnimator包含ofInt和ofFloat方法,分别用于对浮点型和整数型的数据进行动画操作的,但实际上ValueAnimator中还有一个ofObject方法,是用于对任意对象进行动画操作的。但是相比之下,对象的操作明显复杂一些,因为系统将完全无法知道如何从初始对象过渡到结束对象,因此这个时候我们就需要实现一个自己的TypeEvaluator来告知系统如何进行过渡。

先定义一个Point类,x,y表示坐标

public class Point {    private float x;    private float y;    public Point(float x, float y) {        super();        this.x = x;        this.y = y;    }    public float getX() {        return x;    }    public void setX(float x) {        this.x = x;    }    public float getY() {        return y;    }    public void setY(float y) {        this.y = y;    }}

再定义一个TypeEvaluator

public class PointEvaluator implements TypeEvaluator{    @Override    public Object evaluate(float fraction, Object startValue, Object endValue) {        Point startPoint=(Point) startValue;        Point endPoint=(Point) endValue;        float x=startPoint.getX()+fraction*(endPoint.getX()-startPoint.getX());        float y=startPoint.getY()+fraction*(endPoint.getX()-startPoint.getX());        Point point=new Point(x, y);        return point;    }}

接下来让两个Point之间进行平滑过渡

    Point p1=new Point(0, 0);    Point p2=new Point(300,300);    ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), p1,p2);    anim.setDuration(5000);    anim.start();

但这样依然看不出效果,我们现在自定义一个圆球(View)

public class MyAnimView extends View{    private Point currentPoint;    private Paint mPaint;    public MyAnimView(Context context, AttributeSet attrs) {        super(context, attrs);        mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);        mPaint.setColor(Color.BLUE);    }    @Override    protected void onDraw(Canvas canvas) {        //为空,绘制(刚开始)        if(currentPoint==null){            currentPoint=new Point(50f, 50f);            //画圆            drawCircle(canvas);            //开启动画            startAnim();        }else{//不为空,继续绘制(过程中)            //继续画            drawCircle(canvas);          }    }    private void startAnim() {        //初始点        Point startPoint=new Point(50f, 50f);        //结束点        Point endPoint=new Point(getWidth()-50f,getHeight()-50f);        ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), startPoint,endPoint);        //开始监听动画的更新        anim.addUpdateListener(new AnimatorUpdateListener() {            //每次更新,animation.getAnimatedValue()会将PointEvaluator中的evaluate()结果返回            //再进行重绘            @Override            public void onAnimationUpdate(ValueAnimator animation) {                currentPoint=(Point) animation.getAnimatedValue();                invalidate();            }        });        anim.setDuration(5000);        anim.start();    }    private void drawCircle(Canvas canvas) {        float x=currentPoint.getX();        float y=currentPoint.getY();        canvas.drawCircle(x, y, 50f, mPaint);    }}

ObjectAnimator的高级用法

将ObjectAnimator扩展,能够进行颜色动画效果

因为ObjectAnimator操作的属性需要setter,getter,所以在上述自定义圆球中,加入该属性

public class MyAnimView extends View{    ...    private String color;    public String getColor() {        return color;    }    public void setColor(String color) {        this.color = color;        mPaint.setColor(Color.parseColor(color));        invalidate();    }    ...}

接下来编写一个用于告知系统如何进行颜色过渡的TypeEvaluator

public class ColorEvaluator implements TypeEvaluator{    private int mCurrentRed=-1;    private int mCurrentGreen=-1;    private int mCurrentBlue=-1;    @Override    public Object evaluate(float fraction, Object startValue, Object endValue) {        String startColor=(String) startValue;        String endColor=(String) endValue;        int startRed = Integer.parseInt(startColor.substring(1, 3), 16);          int startGreen = Integer.parseInt(startColor.substring(3, 5), 16);          int startBlue = Integer.parseInt(startColor.substring(5, 7), 16);          int endRed = Integer.parseInt(endColor.substring(1, 3), 16);          int endGreen = Integer.parseInt(endColor.substring(3, 5), 16);          int endBlue = Integer.parseInt(endColor.substring(5, 7), 16);         // 初始化颜色的值          if (mCurrentRed == -1) {              mCurrentRed = startRed;          }          if (mCurrentGreen == -1) {              mCurrentGreen = startGreen;          }          if (mCurrentBlue == -1) {              mCurrentBlue = startBlue;          }          // 计算初始颜色和结束颜色之间的差值          int redDiff = Math.abs(startRed - endRed);          int greenDiff = Math.abs(startGreen - endGreen);          int blueDiff = Math.abs(startBlue - endBlue);          int colorDiff = redDiff + greenDiff + blueDiff;          if (mCurrentRed != endRed) {              mCurrentRed = getCurrentColor(startRed, endRed, colorDiff, 0,                      fraction);          } else if (mCurrentGreen != endGreen) {              mCurrentGreen = getCurrentColor(startGreen, endGreen, colorDiff,                      redDiff, fraction);          } else if (mCurrentBlue != endBlue) {              mCurrentBlue = getCurrentColor(startBlue, endBlue, colorDiff,                      redDiff + greenDiff, fraction);          }          // 将计算出的当前颜色的值组装返回          String currentColor = "#" + getHexString(mCurrentRed)                  + getHexString(mCurrentGreen) + getHexString(mCurrentBlue);          return currentColor;     }    /**      * 根据fraction值来计算当前的颜色。      */      private int getCurrentColor(int startColor, int endColor, int colorDiff,              int offset, float fraction) {          int currentColor;          if (startColor > endColor) {              currentColor = (int) (startColor - (fraction * colorDiff - offset));              if (currentColor < endColor) {                  currentColor = endColor;              }          } else {              currentColor = (int) (startColor + (fraction * colorDiff - offset));              if (currentColor > endColor) {                  currentColor = endColor;              }          }          return currentColor;      }      /**      * 将10进制颜色值转换成16进制。      */      private String getHexString(int value) {          String hexString = Integer.toHexString(value);          if (hexString.length() == 1) {              hexString = "0" + hexString;          }          return hexString;      } }

首先在evaluate()方法当中获取到颜色的初始值和结束值,并通过字符串截取的方式将颜色分为RGB三个部分,并将RGB的值转换成十进制数字,那么每个颜色的取值范围就是0-255。接下来计算一下初始颜色值到结束颜色值之间的差值,这个差值很重要,决定着颜色变化的快慢,如果初始颜色值和结束颜色值很相近,那么颜色变化就会比较缓慢,而如果颜色值相差很大,比如说从黑到白,那么就要经历255*3这个幅度的颜色过度,变化就会非常快。

那么控制颜色变化的速度是通过getCurrentColor()这个方法来实现的,这个方法会根据当前的fraction值来计算目前应该过度到什么颜色,并且这里会根据初始和结束的颜色差值来控制变化速度,最终将计算出的颜色进行返回。

最后,由于我们计算出的颜色是十进制数字,这里还需要调用一下getHexString()方法把它们转换成十六进制字符串,再将RGB颜色拼装起来之后作为最终的结果返回。

实现颜色背景动画的过渡

    private void startAnim() {        //初始点        Point startPoint=new Point(50f, 50f);        //结束点        Point endPoint=new Point(getWidth()-50f,getHeight()-50f);        ValueAnimator anim=ValueAnimator.ofObject(new PointEvaluator(), startPoint,endPoint);        //开始监听动画的更新        anim.addUpdateListener(new AnimatorUpdateListener() {            //每次更新,animation.getAnimatedValue()会将PointEvaluator中的evaluate()结果返回            //再进行重绘            @Override            public void onAnimationUpdate(ValueAnimator animation) {                currentPoint=(Point) animation.getAnimatedValue();                invalidate();            }        });        //颜色背景动画        ObjectAnimator anim2 = ObjectAnimator.ofObject(this, "color", new ColorEvaluator(),"#0000FF", "#FF0000");          AnimatorSet animSet=new AnimatorSet();        animSet.play(anim).with(anim2);        animSet.setDuration(5000);        animSet.start();    }

Interpolator的用法

补间器,它的主要作用是可以控制动画的变化速率,比如一些线性/非线性运动。就是说,动画改变的速率不是一成不变的。

Android内置的Interpolator,直接拿来用就好了,setsetInterpolator()。

  • AccelerateDecelerateInterpolator 在动画开始与结束的地方速率改变比较慢,在中间的时候加速
  • AccelerateInterpolator 在动画开始的地方速率改变比较慢,然后开始加速
  • AnticipateInterpolator 开始的时候向后然后向前甩
  • AnticipateOvershootInterpolator 开始的时候向后然后向前甩一定值后返回最后的值
  • BounceInterpolator 动画结束的时候弹起
  • CycleInterpolator 动画循环播放特定的次数,速率改变沿着正弦曲线
  • DecelerateInterpolator 在动画开始的地方快然后慢
  • LinearInterpolator 以常量速率改变
  • OvershootInterpolator 向前甩一定值后再回到原来位置

ViewPropertyAnimator的用法

直接在控件后上设置动画

    textview.animate().alpha(0f);      textview.animate().x(500).y(500);      textview.animate().x(500).y(500).setDuration(5000); 

注意的地方:

  • 整个ViewPropertyAnimator的功能都是建立在View类新增的animate()方法之上的,这个方法会创建并返回一个ViewPropertyAnimator的实例,之后的调用的所有方法,设置的所有属性都是通过这个实例完成的。

  • 大家注意到,在使用ViewPropertyAnimator时,我们自始至终没有调用过start()方法,这是因为新的接口中使用了隐式启动动画的功能,只要我们将动画定义完成之后,动画就会自动启动。并且这个机制对于组合动画也同样有效,只要我们不断地连缀新的方法,那么动画就不会立刻执行,等到所有在ViewPropertyAnimator上设置的方法都执行完毕后,动画就会自动启动。当然如果不想使用这一默认机制的话,我们也可以显式地调用start()方法来启动动画。

  • ViewPropertyAnimator的所有接口都是使用连缀的语法来设计的,每个方法的返回值都是它自身的实例,因此调用完一个方法之后可以直接连缀调用它的另一个方法,这样把所有的功能都串接起来,我们甚至可以仅通过一行代码就完成任意复杂度的动画功能。

布局动画LayoutAnimations

主要使用LayoutTransition为布局的容器设置动画,当容器中的视图层次发生变化时存在过渡的动画效果。

基本你用法如下:

    LayoutTransition transition = new LayoutTransition();      transition.setAnimator(LayoutTransition.CHANGE_APPEARING,              transition.getAnimator(LayoutTransition.CHANGE_APPEARING));      transition.setAnimator(LayoutTransition.APPEARING,              null);      transition.setAnimator(LayoutTransition.DISAPPEARING,              null);      transition.setAnimator(LayoutTransition.CHANGE_DISAPPEARING,              null);      mGridLayout.setLayoutTransition(transition);  

过渡的类型一共有四种:

  • LayoutTransition.APPEARING 当一个View在ViewGroup中出现时,对此View设置的动画
  • LayoutTransition.CHANGE_APPEARING 当一个View在ViewGroup中出现时,对此View对其他View位置造成影响,对其他View设置的动画
  • LayoutTransition.DISAPPEARING 当一个View在ViewGroup中消失时,对此View设置的动画
  • LayoutTransition.CHANGE_DISAPPEARING 当一个View在ViewGroup中消失时,对此View对其他View位置造成影响,对其他View设置的动画

还可以自定义动画

    mTransition.setAnimator(LayoutTransition.APPEARING, (mAppear                  .isChecked() ? ObjectAnimator.ofFloat(this, "scaleX", 0, 1).setDuration(200)                  : null));  
0 0