1. 程式人生 > >Android動畫三部曲之一 View Animation & LayoutAnimation

Android動畫三部曲之一 View Animation & LayoutAnimation

本篇文章對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庫:

公共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圖片。幀動畫設定很簡單,只需要把每一幀對應的圖片按照順序新增進去,然後設定每一幀的顯示時長,然後為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到此結束~
感謝大家支援!如有錯誤,請指出~
謝謝~

參考:

相關推薦

Android動畫三部曲之一 View Animation & LayoutAnimation

本篇文章對android的Tween動畫和幀動畫以及佈局動畫進行總結。 Tween動畫 Tween動畫又稱補間動畫。通過對view的位置、大小、透明度、角度的改變來實現動畫效果。 補間動畫的基類是Animation。我們通常使用它的直接子類R

Android動畫效果之Frame Animation(逐幀動畫

想要 顯示 star 載體 rop 復雜 ide sources post 前言: 上一篇介紹了Android的Tween Animation(補間動畫) Android動畫效果之Tween Animation(補間動畫),今天來總結下Android的另外一種動

Android動畫控制元件之Animation

概述: android的動畫效果包括:移動,漸變透明度,旋轉,縮放。 實現動畫的方式有兩種:在java程式碼中動態實現,在xml中靜態實現。 demo 動態實現: /*

Android 動畫之補間動畫(View Animation)

Android 中補間動畫包括下面四種: 1.透明度動畫 (AlphaAnimation) 2.縮放動畫 (ScaleAnimation) 3.平移動畫 (TranslateAnimation) 4.旋轉動畫 (RotateAnimation) 補間動畫是專門針對V

Android三種動畫View Animation(補間動畫) 、Drawable Animation(幀動畫) 、Property Animation(屬性動畫)(下)

轉載:http://blog.csdn.net/lmj623565791/article/details/38092093 三種動畫的優缺點: (1)Frame Animation(幀動畫)主要用於播放一幀幀準備好的圖片,類似GIF圖片,優點是使用簡單

Android 動畫View Animation詳解(一)

安卓平臺目前提供了兩大類動畫,在Android 3.0之前,一大類是View Animation,包括Tween animation(補間動畫),Frame animation(幀動畫),在android3.0中又引入了一個新的動畫系統:property ani

Android-View Animation(檢視動畫)

     Android系統提供了兩種動畫框架:property動畫(屬性動畫)和View動畫(檢視動畫)。這兩個動畫系統都是可行的方案,但在一般情況下,屬性動畫系統被優先使用,因為它更靈活,並且提供

Android 動畫學習(一)之View Animation

Android動畫初步         動畫(Animation)在我們日常的Android開發工作當中使用得較為頻繁,尤其對於Android遊戲這個動畫的集合體,掌握動畫開發的重要性毋庸置疑。同

android.view.animation(2) - 插值器Interpolator

tin logs lis png 16px tor 文件 anim near public interface Interpolator implements TimeInterpolator android.view.animation.Interpolator

Android界面實現】View Animation 使用介紹

ref 轉載 HA ceshi 很多 ons 伸縮 ets 時間設置 ? ? 轉載請註明出處:http://blog.csdn.net/zhaokaiqiang19

Android動畫筆記之Animation

簡介 Android提供了兩種機制,您可以使用它們來建立簡單的動畫:補間動畫,您可以在其中告訴Android對檢視內容執行一系列簡單的轉換(位置,大小,旋轉等); 和逐幀動畫,一個接一個地載入一系列Drawable資源。 兩種動畫型別都可以在任何View物件中使用,以提供簡單的旋轉計

android基礎--列表資料View重新整理動畫

該效果類似於iPhone中View的切換動畫效果 效果一: 效果二: 效果三: 效果四: 效果五(迴旋效果一): 效果六(迴旋效果二): 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15

Android動畫精講一 從setTranslationX談屬性動畫view動畫的區別

                            最近又用到了動畫,決定把幾次專案裡用到的動畫走過的彎路總結一下,順便梳理下android的動畫體系。眾所周知,android動畫分三類:一是View 動畫,又叫Tween動畫,二是frame 動畫(幀動畫),又叫drawable 動畫,三是屬性動畫,即p

android進階4step1:Android動畫處理與自定義View——SurfaceView

SurfaceView簡介 1、SurfaceView與View的區別 2、SurfaceView的具體使用場景 3、如何使用SurfaceView 一、SurfaceView與View的區別 1、不使用onDraw 2、非UI執行緒繪製 3、獨立

android進階4step1:Android動畫處理與自定義View——自定義View

為什麼要自定義控制元件 特定的顯示風格 處理特有的使用者互動 優化我們的佈局 封裝等... 如何自定義控制元件 自定義屬性的宣告與獲取 測量onMeasure 繪製onDraw 狀態的儲存與恢復 步驟一、自定義屬性宣告與獲取

android進階4step1:Android動畫處理與自定義View——轉場動畫

以下都需要執行在5.0以上 一、揭露動畫效果 參考:使用Circular Reveal為你的應用新增揭露動畫效果 最主要的類Circular Reveal 官方將這一動畫稱為揭露效果,它在官網中的描述是這樣的: 當您顯示或隱藏一組 UI 元素時,揭露動畫可為使用者提供視覺

Android 有點選動畫效果的View

Bitmap extractAlpha () Returns a new bitmap that captures the alpha values of the original. This may be drawn with Canvas.drawBitmap(), where the color(s

程式碼藝術-Android針對帶有複雜動畫自定義view的程式碼設計

Android自定義view有時需要完成一些複雜的動畫,這時後會發現程式碼看起來還是蠻複雜的,如何實現讓程式碼結構清晰,對提供程式碼穩定性以及對程式碼修改有著非常大的幫助。下面是我提供的一種思路。 思路原理: 我們知道一個動畫其實是有固定流程的,比如一個走動的

詳解Android動畫之Tween Animation

轉載地址:http://blog.csdn.net/liuhe688/article/details/6660823 前面講了動畫中的Frame動畫,今天就來詳細講解一下Tween動畫的使用。 同樣,在開始例項演示之前,先引用官方文件中的一段話:

Android動畫-Frame Animation(幀動畫

Android動畫主要分為以下三類: Tweened animation(補間動畫)- 在android3.0(API11)之前支援,該動畫僅僅支援對View操作,而且View在做動畫的時候,View相應的實際屬性值並沒有發生改變,例如:一個Button起始位置left,to