zoukankan      html  css  js  c++  java
  • Android动画三部曲之中的一个 View Animation & LayoutAnimation

    转载请注明出处:http://blog.csdn.net/crazy1235/article/details/50612827

    本篇文章对android的Tween动画帧动画以及布局动画进行总结。


    Tween动画

    Tween动画又称补间动画。通过对view的位置、大小、透明度、角度的改变来实现动画效果。

    补间动画的基类是Animation。

    我们通常使用它的直接子类RotateAnimationTranslateAnimationScaleAnimationAlphaAnimation

    补间动画能够通过xml进行定义(res/anim/xxx),然后通过AnimationUtils类进行载入;也能够通过全然代码进行设置。


    XML语法介绍

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:interpolator="@[package:]anim/interpolator_resource"
        android:shareInterpolator=["true" | "false"] >
        <alpha
            android:fromAlpha="float"
            android:toAlpha="float" />
        <scale
            android:fromXScale="float"
            android:toXScale="float"
            android:fromYScale="float"
            android:toYScale="float"
            android:pivotX="float"
            android:pivotY="float" />
        <translate
            android:fromXDelta="float"
            android:toXDelta="float"
            android:fromYDelta="float"
            android:toYDelta="float" />
        <rotate
            android:fromDegrees="float"
            android:toDegrees="float"
            android:pivotX="float"
            android:pivotY="float" />
        <set>
            ...
        </set>
    </set>

    图片名称

    Animation类定义了非常多常量和变量的初始值,比方:

    public static final int INFINITE = -1;
    
    public static final int RESTART = 1;
    
    public static final int REVERSE = 2;

    主要用到它的子类以及AnimationListener :

    public static interface AnimationListener {
            /**
             * 动画開始的时候回调
             *
             * @param animation The started animation.
             */
            void onAnimationStart(Animation animation);
            /**
             * 动画结束的时候回调。

    可是当设置动画反复次数为INFINITE的时候,该方法不会回调。 * * @param animation The animation which reached its end. */ void onAnimationEnd(Animation animation); /** * 动画反复播放的时候回调 * * @param animation The animation which was repeated. */ void onAnimationRepeat(Animation animation); }

    加入此监听器能够对动画做很多其它的操作。


    插值器 – Interpolator

    介绍动画之前,得先说说”插值器”。

    插值器的意思就是在播放动画的时候。改变播放的速率。能够使动画越来越快,或者越来越慢等。

    经常使用的是一下九个插值器:

    Baseinterpolator子类 Resource ID 描写叙述
    AccelerateInterpolator @android:anim/accelerate_interpolator 加速变化(開始慢,越来越快)
    DecelerateInterpolator @android:anim/decelerate_interpolator 减速变化(開始快,越来越慢)
    AccelerateDecelerateInterpolator @android:anim/accelerate_decelerate_interpolator 先加速后减速(中间速度最快)
    LinearInterpolator @android:anim/linear_interpolator 线性均匀变化
    OvershootInterpolator @android:anim/overshoot_interpolator 超出结尾的临界值。然后在缓慢回到结束值
    AnticipateInterpolator @android:anim/anticipate_interpolator 先向相反的方向改变一点,然后在加速播放
    AnticipateOvershootInterpolator @android:anim/anitcipate_overshoot_interpolator 先向相反的方向改变一点,然后在加速播放至超出结束值一点,然后在缓慢回到结束值
    BounceInterpolator @android:anim/bounce_interpolator 动画快结束的时候,模拟球落地的回弹效果
    CycleInterpolator @android:anim/cycle_interpolator 动画循环播放指定的次数

    自己定义Interpolator

    一般来说,官方API给的这几个插值器就够有用了。只是还能够自己定义Interpolator。

    能够简单的对系统的插值器进行一些參数值的改动:

    <?xml version="1.0" encoding="utf-8"?>
    <InterpolatorName xmlns:android="http://schemas.android.com/apk/res/android"
        android:attribute_name="value" />

    这里推荐大家一个第三方的Interpolator库:

    https://github.com/cimi-chen/EaseInterpolator


    公共XML属性及相应的方法

    属性名称 相应的方法 描写叙述
    android:duration setDuration(long) 动画持续的时间长度(单位是miliseconds)
    android:interpolator setInterpolator(Interpolator) 设置动画播放时的插值器
    android:repeatCount setRepeatCount(int) 设置动画播放反复次数
    android:repeatMode setRepeatMode(int) 设置动画反复的方式(当repeat count>0时才有效) “reverse“(2) or “restart“(1)
    android:startOffset setStartOffset(long) 设置动画開始播放的延迟时间
    android:fillAfter setFillAfter(boolean) 设置为true时。视图会停留在动画结束的状态。
    android:fillBefore setFillBefore(boolean) 默认值是true,视图会停留在动画開始的状态
    android:fillEnable setFillEnable(boolean) 默认值是false。假设是true,动画将会应用fillBefore值。否则,fillBefore的值会被忽略。transformation会在动画结束的时候被应用。
    android:detachWallpaper setDetachWallpaper(boolean) 默认值是false。假设为true。而且动画窗口有一个壁纸的话,那么动画仅仅会应用给window,墙纸是静态不动的
    android:zAdjustment setZAdjustment(int) 同意在动画播放期间,调整播放内容在Z轴方向的顺序。

    top“(1) or “normal“(0) or “bottom“(-1)

    android:zAdjustment:同意在动画播放期间,调整播放内容在Z轴方向的顺序:

    • normal(0):正在播放的动画内容保持当前的Z轴顺序,
    • top(1):在动画播放期间,强制把当前播放的内容放到其它内容的上面;
    • bottom(-1):在动画播放期间,强制把当前播放的内容放到其它内容之下

    ScaleAnimation – 缩放动画

    XML属性名称 描写叙述
    android:fromXScale 动画起始时,X轴坐标的伸缩尺寸。0.0表示收缩到没有。1.0表示正常没伸缩。>1.0表示放大。<1.0表示收缩。
    android:toXScale 动画结束时X轴坐标的伸缩尺寸
    android:fromYScale 动画起始时Y轴坐标的伸缩尺寸
    android:toYScale 动画结束时Y轴坐标的伸缩尺寸
    android:pivotX 缩放动画作用点在X轴方向上的位置。

    android:pivotX=”50”表示绝对定位,相对于零点偏移50 –> Animation.ABSOLUTE android:pivotX=”50%”表示相对控件本身 –> Animation.RELATE_TO_SELF android:pivotX=”50%p”表示相对控件的父控件 –> Animation.RELATE_TO_PARENT

    android:pivotY 缩放动画作用点在Y轴方向上的位置
    xml定义缩放动画
    <?xml version="1.0" encoding="utf-8"?>
    <scale xmlns:android="http://schemas.android.com/apk/res/android"
        android:background="@color/blue_light"
        android:duration="1000"
        android:fillAfter="false"
        android:fillBefore="true"
        android:fromXScale="1"
        android:fromYScale="1"
        android:interpolator="@android:anim/accelerate_decelerate_interpolator"
        android:pivotX="50%"
        android:pivotY="50%"
        android:repeatCount="1"
        android:repeatMode="restart"
        android:startOffset="500"
        android:toXScale="0"
        android:toYScale="0"
        android:zAdjustment="bottom" />

    然后通过AnimationUtils类装载动画,进行应用。

    Animation scaleAnimation =  AnimationUtils.loadAnimation(this, R.anim.scale_anim);
    targetIv.startAnimation(scaleAnimation);
    代码定义缩放动画
    ScaleAnimation scaleAnimation = new ScaleAnimation(1.0f, 0.5f, 1.0f, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f, Animation.RELATIVE_TO_SELF, 0.5f);
    scaleAnimation.setDuration(1000);
    scaleAnimation.setInterpolator(new OvershootInterpolator());
    scaleAnimation.setFillAfter(true);
    targetIv.startAnimation(scaleAnimation);

    ScaleAnimation有4个构造方法。

    public ScaleAnimation(Context context, AttributeSet attrs) {}
    public ScaleAnimation(float fromX, float toX, float fromY, float toY) {}
    public ScaleAnimation(float fromX, float toX, float fromY, float toY, float pivotX, float pivotY) {}
    public ScaleAnimation(float fromX, float toX, float fromY, float toY, int pivotXType, float pivotXValue, int pivotYType, float pivotYValue) {}

    第一个构造用于从资源文件里载入资源。我们主要用后三个。后面三个构造的差别就在设置变换中轴点与否。

    不指定pivotXType和pivotYType的话。默认採用ABSOLUTE形式,pivotX与pivotY的值都是相对于(0,0)左上角偏移的。

    pivotXType可设置的參数有三种:ABSOLUTE、RELATE_TO_SELF、RELATE_TO_PARENT。

    • ABSOLUTE表示当前设置的pivotX和pivotY值是绝对值,相对于左上角偏移。

      比方:android:pibotX=”50”

    • RELATE_TO_SELF表示设置的pivotX和pivotY是相对值。比方:android:pivotX = “50%”表示X方向中轴点在正中间。 取值范围是[0% ~ 100%]
    • RELATE_TO_PARENT也是表示相对值。是相对于该视图的父控件而言。比方:android:pivotX = “50%p”表示X方向中轴点是其父控件的中间位置。取值范围是[0% ~ 100%]

    效果例如以下:

    这里写图片描写叙述


    RotateAnimation – 旋转动画

    XML属性名称 描写叙述
    android:fromDegrees 动画起始的角度(可正可负)
    android:toDegrees 动画终止的角度(可正可负)
    android:pivotX 旋转作用点在X轴方向上的位置。android:pivotX=”50”表示绝对定位,相对于零点偏移50 android:pivotX=”50%”表示相对控件本身 android:pivotX=”50%p”表示相对控件的父控件
    android:pivotY 旋转作用点在Y轴方向上的位置
    xml中设置旋转动画
    <?

    xml version="1.0" encoding="utf-8"?> <rotate xmlns:android="http://schemas.android.com/apk/res/android" android:duration="2500" android:fillAfter="true" android:fromDegrees="-20" android:interpolator="@android:anim/overshoot_interpolator" android:pivotX="50%" android:pivotY="50%" android:toDegrees="320" />

    代码中设置旋转动画
    RotateAnimation rotateAnimation = new RotateAnimation(0.0f, 550.0f, Animation.RELATIVE_TO_SELF, 0.3f, Animation.RELATIVE_TO_SELF, 0.3f);
    rotateAnimation.setDuration(1500);
    rotateAnimation.setInterpolator(new OvershootInterpolator());
    rotateAnimation.setFillAfter(true);
    targetIv.startAnimation(rotateAnimation);

    效果图例如以下:

    这里写图片描写叙述


    TranslateAnimation – 平移动画

    XML属性名称 描写叙述
    android:fromXDelta 平移动画起始位置X轴坐标
    android:toXDelta 平移动画结束位置X轴坐标
    android:fromYDelta 平移动画起始位置Y轴坐标
    android:toYDelta 平移动画结束位置Y轴坐标
    xml中设置平移动画:
    <?xml version="1.0" encoding="utf-8"?>
    <translate xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="1000"
        android:fromXDelta="0"
        android:fromYDelta="0"
        android:interpolator="@android:anim/anticipate_overshoot_interpolator"
        android:toXDelta="50%p"
        android:toYDelta="50%p" />
    代码中设置平移动画
    TranslateAnimation translateAnimation = new TranslateAnimation(0, 200, 0, 0);
    translateAnimation.setDuration(1000);
    translateAnimation.setInterpolator(new AnticipateOvershootInterpolator());
    targetIv.startAnimation(translateAnimation);

    这里写图片描写叙述


    AlphaAnimation – 渐变动画

    XML属性名称 描写叙述
    android:fromAlpha 动画開始时操作对象的alpha值
    android:toAlpha 动画终止时操作对象的alpha值
    xml中设置渐变动画:
    <?

    xml version="1.0" encoding="utf-8"?> <alpha xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:fromAlpha="1.0" android:interpolator="@android:anim/linear_interpolator" android:repeatCount="1" android:repeatMode="reverse" android:toAlpha="0.0" />

    代码中设置渐变动画:
    AlphaAnimation alphaAnimation = new AlphaAnimation(1.0f, 0.2f);
    alphaAnimation.setDuration(1500);
    alphaAnimation.setInterpolator(new AccelerateDecelerateInterpolator());
    alphaAnimation.setRepeatMode(Animation.REVERSE);
    alphaAnimation.setRepeatCount(1);
    targetIv.startAnimation(alphaAnimation);

    这里写图片描写叙述


    AnimationSet – 动画集合

    上面都是一个个的单独的动画,我们能够将非常多个单独的动画组合到一起成为一个集合。

    动画集合也能够在xml中设置。须要用标签包含其它简单的动画。

    比上述公共动画属性多了一个android:shareInterpolator=”boolean”,表示是否对子动画设置相同的插值器。

    xml中设置set动画集合
    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        android:shareInterpolator="false">
        <alpha
            android:duration="1500"
            android:fillAfter="true"
            android:fromAlpha="1.0"
            android:interpolator="@android:anim/accelerate_interpolator"
            android:toAlpha="0.2" />
        <scale
            android:duration="1000"
            android:fromXScale="0.8"
            android:fromYScale="0.8"
            android:interpolator="@android:anim/linear_interpolator"
            android:pivotX="60%"
            android:pivotY="20%"
            android:startOffset="1500"
            android:toXScale="0.3"
            android:toYScale="0.5" />
        <translate
            android:duration="1000"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:interpolator="@android:anim/bounce_interpolator"
            android:startOffset="2500"
            android:toXDelta="200"
            android:toYDelta="200" />
        <rotate
            android:duration="1000"
            android:fromDegrees="50"
            android:interpolator="@android:anim/anticipate_overshoot_interpolator"
            android:pivotX="50%p"
            android:pivotY="50%p"
            android:startOffset="3500"
            android:toDegrees="360" />
    </set>


    我们来看一个现象:
    设置了上面的set动画之后。開始执行的时候,会发现渐变动画開始执行的时候,会先变小。旋转一个角度。然后才開始动画。细致分析xml代码之后,发现是在动画開始的时候,把scale和rotate中的初始状态给应用了。这时候想起了android:fillBefore属性。
    然后在scale、rotate 动画里加入了android:fillBefore=”false”属性之后。发现还是不好使。查看Animation类的源代码发现。fillBefore必须在设置fillEnable=”true”的时候才神效。而且fillBefore的默认值是true,所以才会出现上述情况。

    再次改动之后。代码例如以下:

    <?xml version="1.0" encoding="utf-8"?>
    <set xmlns:android="http://schemas.android.com/apk/res/android"
        android:fillAfter="true"
        android:shareInterpolator="false">
        <alpha
            android:duration="1500"
            android:fillAfter="true"
            android:fromAlpha="1.0"
            android:interpolator="@android:anim/accelerate_interpolator"
            android:toAlpha="0.2" />
        <scale
            android:duration="1000"
            android:fillBefore="false"
            android:fillEnabled="true"
            android:fromXScale="0.8"
            android:fromYScale="0.8"
            android:interpolator="@android:anim/linear_interpolator"
            android:pivotX="60%"
            android:pivotY="20%"
            android:startOffset="1500"
            android:toXScale="0.3"
            android:toYScale="0.5" />
        <translate
            android:duration="1000"
            android:fromXDelta="0"
            android:fromYDelta="0"
            android:interpolator="@android:anim/bounce_interpolator"
            android:startOffset="2500"
            android:toXDelta="200"
            android:toYDelta="200" />
        <rotate
            android:duration="1000"
            android:fillBefore="false"
            android:fillEnabled="true"
            android:fromDegrees="50"
            android:interpolator="@android:anim/anticipate_overshoot_interpolator"
            android:pivotX="50%p"
            android:pivotY="50%p"
            android:startOffset="3500"
            android:toDegrees="360" />
    </set>

    效果例如以下:

    这里写图片描写叙述


    Frame动画

    Frame动画就是把图片一帧一帧的播放出来的显示效果,相似于gif图片。帧动画设置非常easy。仅仅须要把每一帧相应的图片依照顺序加入进去,然后设置每一帧的显示时长,然后为view控件设置该动画,播放即可了。

    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/person1" android:duration="100" /> <item android:drawable="@drawable/person2" android:duration="100" /> <item android:drawable="@drawable/person3" android:duration="100" /> <ite android:drawable="@drawable/person4" android:duration="100" /> <item android:drawable="@drawable/person5" android:duration="100" /> <item android:drawable="@drawable/person6" android:duration="100" /> <item android:drawable="@drawable/person7" android:duration="100" /> </animation-list>

    给ImageView设置动画:

    targetIv.setBackgroundResource(R.drawable.frame_anim);
    AnimationDrawable animationDrawable = (AnimationDrawable) targetIv.getBackground();
    animationDrawable.start();
    代码中设置帧动画
    AnimationDrawable animationDrawable = new AnimationDrawable();
    animationDrawable.setOneShot(false);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable.person1), 200);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable.person2), 200);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable.person3), 200);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable.person4), 200);
    animationDrawable.addFrame(getResources().getDrawable(R.drawable.person5), 200);
    targetIv.setImageDrawable(animationDrawable);
    animationDrawable.start();

    这里写图片描写叙述


    LayoutAnimationController

    Tween Animation和Frame Animation都是针对单个view操作的。而LayoutAnimationController能够针对一个ViewGroup进行动画操作,能够让一组view的每一个view依照一定的规则展示动画。
    比方:能够针对listView、gridView或者recyclerView,定义item的出场动画,而不是非常死板的一下子全显示出来。

    一般对ListView使用layoutAnimation动画,对GridView使用gridLayoutAnimation动画。

    对RecyclerView来说。正常情况下仅仅能使用layoutAnimation动画。应用gridLayoutAnimation动画的时候会报错。不错能够针对RecyclerView生成一个子类做一下处理进行支持gridLayoutAnimation动画。

    xml属性 相应的方法 描写叙述
    android:delay setDelay(float) 动画播放的延迟时间
    android:animationOrder setOrder(int) 子view播放动画的顺序 [ normal
    android:interpolator setInterpolator(Interpolator) setIntepolator(Context, @InterpolatorRes int) 插值器
    android:animation LayoutAnimationController(animation) 指定子view的动画
    xml定义LayoutAnimation
    <?xml version="1.0" encoding="utf-8"?

    > <layoutAnimation xmlns:android="http://schemas.android.com/apk/res/android" android:animation="@anim/item_list_anim" android:animationOrder="normal" android:delay="0.2" android:interpolator="@android:anim/bounce_interpolator" />

    <?xml version="1.0" encoding="utf-8"?

    > <set xmlns:android="http://schemas.android.com/apk/res/android" android:duration="1000" android:shareInterpolator="true"> <alpha android:fromAlpha="0.0" android:toAlpha="1.0" /> <translate android:fromXDelta="-100%" android:toXDelta="0%" /> </set>

    代码中定义LayoutAnimation
    public LayoutAnimationController(Animation animation) {
        this(animation, 0.5f);
    }
    public LayoutAnimationController(Animation animation, float delay) {
        mDelay = delay;
        setAnimation(animation);
    }

    LayoutAnimationController有三个构造函数,经常使用的时候上面两个。

    delay表示每一个子view启动动画的延迟时间,默认是0.5f。delay以秒为单位

    Animation animation = AnimationUtils.loadAnimation(this, R.anim.item_list_anim);
            LayoutAnimationController layoutAnimationController = new LayoutAnimationController(animation);
            layoutAnimationController.setInterpolator(new AccelerateInterpolator());
            layoutAnimationController.setDelay(0.5f);
            layoutAnimationController.setOrder(LayoutAnimationController.ORDER_RANDOM);
            recyclerView.setLayoutAnimation(layoutAnimationController);

    这里写图片描写叙述


    GridLayoutAnimationController

    GridLayoutAnimationController是LayoutAnimationController的子类。针对GridView做动画操作。

    xml属性 相应的方法 描写叙述
    android:delay setDelay(float) 动画播放的延迟时间
    android:columnDelay setColumnDelay(float) 列播放动画的延迟时间
    android:rowDelay setRowDelay(float) 行播放动画的延迟时间
    android:animationOrder setOrder(int) 子view播放动画的顺序 [ normal
    android:animation LayoutAnimationController(animation) 指定子view的动画
    xml中定义
      <GridView
            android:id="@+id/test_grid_view"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:columnWidth="60dp"
            android:gravity="center"
            android:horizontalSpacing="10dp"
            android:layoutAnimation="@anim/grid_layout_anim"
            android:numColumns="3"
            android:padding="10dp"
            android:scrollbars="none"
            android:stretchMode="columnWidth"
            android:verticalSpacing="10dp" />
    <?xml version="1.0" encoding="utf-8"?>
    <gridLayoutAnimation xmlns:android="http://schemas.android.com/apk/res/android"
        android:animation="@anim/item_anim_alpha"
        android:columnDelay="0.5"
        android:direction="bottom_to_top|right_to_left"
        android:directionPriority="row" />
    <?xml version="1.0" encoding="utf-8"?>
    <alpha xmlns:android="http://schemas.android.com/apk/res/android"
        android:duration="500"
        android:fromAlpha="0.0"
        android:interpolator="@android:anim/accelerate_interpolator"
        android:toAlpha="1.0" />
    代码中设置

    相同是使用一个Animation构造出GridLayoutAnimation对象。然后设置各种參数,最后设置此动画GridView即可。

    Animation animation = AnimationUtils.loadAnimation(this, R.anim.item_anim_alpha);
    GridLayoutAnimationController gridLayoutAnimationController = new GridLayoutAnimationController(animation);
    gridLayoutAnimationController.setDirection(GridLayoutAnimationController.DIRECTION_BOTTOM_TO_TOP | GridLayoutAnimationController.DIRECTION_RIGHT_TO_LEFT);
    gridLayoutAnimationController.setDirectionPriority(GridLayoutAnimationController.PRIORITY_ROW);
    gridRecyclerView.setLayoutAnimation(gridLayoutAnimationController);
    

    效果例如以下:

    这里写图片描写叙述


    RecyclerView扩展

    正常情况下,我们能够对RecyclerView使用LayoutAnimation动画。可是假设对RecycleView使用动画的时候出现下面错误:

    AndroidRuntime: FATAL EXCEPTION: main                                                       
    Process: com.jacksen.demo.view, PID: 30770                                                  
    java.lang.ClassCastException: android.view.animation.LayoutAnimationController$AnimationParameters cannot be cast to android.view.animation.GridLayoutAnimationController$AnimationParameters
                       at android.view.animation.GridLayoutAnimationController.getDelayForView(GridLayoutAnimationController.java:299)
                       at android.view.animation.LayoutAnimationController.getAnimationForView(LayoutAnimationController.java:321)
                       at android.view.ViewGroup.bindLayoutAnimation(ViewGroup.java:3717)
                       at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2892)
                       ......

    意思就是GridLayoutAnimationController.AnimationParameters不能强转成LayoutAnimationController.AnimationParameters。

    RecyclerView的出现本来就是替代Listview的,可是它有能够展示出GridView的效果,可是怎么让RecyclerView设置GridLayoutManager的时候应用gridLayoutAnimation动画呢?

    我们先来看看Gridview怎么实现的?

    在GridView源代码里面搜索”LayoutAnimation”关键字发现,仅仅有一个attachLayoutAnimationParameters()的函数。里面将layoutAnimationParameters强转成GridLayoutAnimationController.AnimationParameters。

    @Override
        protected void attachLayoutAnimationParameters(View child,
                ViewGroup.LayoutParams params, int index, int count) {
            GridLayoutAnimationController.AnimationParameters animationParams =
                    (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
            if (animationParams == null) {
                animationParams = new GridLayoutAnimationController.AnimationParameters();
                params.layoutAnimationParameters = animationParams;
            }
            animationParams.count = count;
            animationParams.index = index;
            animationParams.columnsCount = mNumColumns;
            animationParams.rowsCount = count / mNumColumns;
            if (!mStackFromBottom) {
                animationParams.column = index % mNumColumns;
                animationParams.row = index / mNumColumns;
            } else {
                final int invertedIndex = count - 1 - index;
                animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns);
                animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns;
            }
        }

    然后就想到去RecyclerView中去找attachLayoutAnimationParameters()方法,可是没有。其父类ViewGroup里面有此方法:

    protected void attachLayoutAnimationParameters(View child,
                LayoutParams params, int index, int count) {
            LayoutAnimationController.AnimationParameters animationParams =
                        params.layoutAnimationParameters;
            if (animationParams == null) {
                animationParams = new LayoutAnimationController.AnimationParameters();
                params.layoutAnimationParameters = animationParams;
            }
            animationParams.count = count;
            animationParams.index = index;
        }

    由此可见RecyclerView默认实现了ViewGroup的LayoutAnimation。我们在RecyclerView中将此方法重写一下。只是要将mStackFromButtom參数的推断去掉

    public class GridRecyclerView extends RecyclerView {
        public GridRecyclerView(Context context) {
            super(context);
        }
        public GridRecyclerView(Context context, AttributeSet attrs) {
            super(context, attrs);
        }
        public GridRecyclerView(Context context, AttributeSet attrs, int defStyle) {
            super(context, attrs, defStyle);
        }
        @Override
        public void setAdapter(Adapter adapter) {
            super.setAdapter(adapter);
        }
        @Override
        public void setLayoutManager(LayoutManager layout) {
            if (layout instanceof GridLayoutManager) {
                super.setLayoutManager(layout);
            } else {
                throw new ClassCastException("you should only use the GridLayoutManager as LayoutManager when you use this " + this.getClass().getSimpleName() + " class");
            }
        }
        @Override
        protected void attachLayoutAnimationParameters(View child, ViewGroup.LayoutParams params, int index, int count) {
            if (getLayoutManager() != null && getLayoutManager() instanceof GridLayoutManager) {
                GridLayoutAnimationController.AnimationParameters animationParams =
                        (GridLayoutAnimationController.AnimationParameters) params.layoutAnimationParameters;
                if (animationParams == null) {
                    animationParams = new GridLayoutAnimationController.AnimationParameters();
                    params.layoutAnimationParameters = animationParams;
                }
                int mNumColumns = ((GridLayoutManager) getLayoutManager()).getSpanCount();
                animationParams.count = count;
                animationParams.index = index;
                animationParams.columnsCount = mNumColumns;
                animationParams.rowsCount = count / mNumColumns;
                final int invertedIndex = count - 1 - index;
                animationParams.column = mNumColumns - 1 - (invertedIndex % mNumColumns);
                animationParams.row = animationParams.rowsCount - 1 - invertedIndex / mNumColumns;
            } else {
                super.attachLayoutAnimationParameters(child, params, index, count);
            }
        }
    }
    

    当我们使用GridLayoutManager的时候,不能使用此属性。

    /**
         * stackFromEnd is not supported by GridLayoutManager. Consider using
         * {@link #setReverseLayout(boolean)}.
         */
        @Override
        public void setStackFromEnd(boolean stackFromEnd) {
            if (stackFromEnd) {
                throw new UnsupportedOperationException(
                        "GridLayoutManager does not support stack from end."
                                + " Consider using reverse layout");
            }
            super.setStackFromEnd(false);
        }

    此篇blog到此结束~
    感谢大家支持!如有错误。请指出~
    谢谢~


    參考:

    http://developer.android.com/intl/zh-cn/guide/topics/graphics/view-animation.html
    http://www.cnblogs.com/angeldevil/archive/2011/12/02/2271096.html
    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0619/3090.html
    http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2015/0915/3462.html?

    utm_source=tuicool&utm_medium=referral

  • 相关阅读:
    python 并发编程 多线程 event
    python 并发编程 多线程 定时器
    python 并发编程 多线程 信号量
    linux top 查看CPU命令
    python 并发编程 多线程 GIL与多线程
    python 并发编程 多线程 死锁现象与递归锁
    python 并发编程 多线程 GIL与Lock
    python GIL全局解释器锁与互斥锁 目录
    python 并发编程 多线程 GIL全局解释器锁基本概念
    执行python程序 出现三部曲
  • 原文地址:https://www.cnblogs.com/yangykaifa/p/7366364.html
Copyright © 2011-2022 走看看