RecyclerAdapter之添加動畫(策略模式)

上篇「RecyclerView.Adapter優化了嗎?」主要講了RecyclerView.Adapter的優化代碼以及添加了item的click方法具體實現原理,這篇在原來的基礎上新增列表動畫,後續還會擴展更多功能,供你們學習,支持我就Star一下「BaseRecyclerViewAdapterHelper」。java

效果如何?

自定義動畫.gif

縮放+漸現.gif

從下到上+從左到右.gif

如何使用?

// 一行代碼搞定(默認爲漸顯效果)
quickAdapter.openLoadAnimation();

若是你想換成別的效果你也能夠android

// 默認提供5種方法(漸顯、縮放、從下到上,從左到右、從右到左)
quickAdapter.openLoadAnimation(BaseQuickAdapter.ALPHAIN);

若是仍是不滿意則能夠自定義效果git

quickAdapter.openLoadAnimation(new BaseAnimation() {
              @Override
              public Animator[] getAnimators(View view) {
                return new Animator[]{
                    ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1),
                    ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
                };
              }
            });

使用就是如此簡單。github

如何作到的?

首先先思考兩個問題算法

  • 添加動畫在哪一個方法裏面添加?性能優化

  • 如何控制動畫加載次數?ide

添加動畫在哪一個方法裏面添加?

onBindViewHolder方法,由於每次填充數據的時候都會調用該方法。wordpress

private int mDuration = 300;
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    // 此處代碼省略,代碼已經在上篇詳細講解過了
    if (isOpenAnimation) {
            BaseAnimation animation = null;
            if (customAnimation != null) {
                animation = customAnimation;
            }else{
                animation = selectAnimation;
            }
            for (Animator anim : animation.getAnimators(holder.itemView)) {
                anim.setDuration(mDuration).start();
                anim.setInterpolator(mInterpolator);
            }       
        }
}

以上代碼,首先判斷是否開啓動畫,而後判斷是不是自定義動畫仍是用戶選擇的自帶動畫,而後對動畫的操做元素進行遍歷執行,執行時間爲300毫秒,因爲上面說了每次填充數據都會調用,因此如何不判斷的話,就會致使上下滑動每次都會重複調用動畫,動畫自己是會耗費性能的。性能

如何控制動畫加載次數?

private int mDuration = 300;
private int mLastPosition = -1;
private boolean isFirstOnly = true;
public void onBindViewHolder(RecyclerView.ViewHolder holder, final int position) {
    // 此處代碼省略,代碼已經在上篇詳細講解過了

    if (isOpenAnimation) {
      if (!isFirstOnly || position > mLastPosition) {
            BaseAnimation animation = null;
            if (customAnimation != null) {
                animation = customAnimation;
            }else{
                animation = selectAnimation;
            }
            for (Animator anim : animation.getAnimators(holder.itemView)) {
                anim.setDuration(mDuration).start();
                anim.setInterpolator(mInterpolator);
            }
             mLastPosition = position;       
        }
    }
}
public void setFirstOnly(boolean firstOnly) {
    isFirstOnly = firstOnly;
}

只須要添加一個mLastPosition來存儲滑動過的位置,而後判斷滑動的位置是否被滑動過,這樣就能夠避免每次都添加動畫了。不過爲了知足喜歡動畫多過於性能的開發者,若是你想要每次滑動都帶動畫能夠設置isFirstOnly屬性便可,默認是不開啓的。學習

Animation的設計

BaseAnimation

public abstract class BaseAnimation {
    public abstract Animator[] getAnimators(View view);
}

AlphaInAnimation

public class AlphaInAnimation extends BaseAnimation {
    private static final float DEFAULT_ALPHA_FROM = 0f;
    private final float mFrom;
    public AlphaInAnimation() {
        this(DEFAULT_ALPHA_FROM);
    }
    public AlphaInAnimation(float from) {
        mFrom = from;
    }
    @Override
    public Animator[] getAnimators(View view) {
        return new Animator[]{ObjectAnimator.ofFloat(view, "alpha", mFrom, 1f)};
    }
}

策略模式定義了一系列的算法,並將每個算法封裝起來,並且使它們還能夠相互替換。策略模式讓算法獨立於使用它的客戶而獨立變化。

在此採用的是「策略模式」,這樣更加靈活,若是須要自定義一個本身的動畫,只須要繼承BaseAnimation實現getAnimators方法便可。

public class CustomAnimation extends BaseAnimation {
    @Override 
    public Animator[] getAnimators(View view) {
       return new Animator[]{ 
      ObjectAnimator.ofFloat(view, "scaleY", 1, 1.1f, 1), 
      ObjectAnimator.ofFloat(view, "scaleX", 1, 1.1f, 1)
     };
 } 
}

設置便可

quickAdapter.openLoadAnimation(new CustomAnimation());

小知識

openLoadAnimation方法

public void openLoadAnimation(@AnimationType int animationType)

在寫這個方法的時候,想是否是用枚舉更合適?可是曾看過多篇性能優化的文章不推薦Enum枚舉,由於性能消耗,其實Android有自帶的枚舉
官方文檔說明,安卓開發應避免使用Enum(枚舉類),由於相比於靜態常量Enum會花費兩倍以上的內存。
Android推薦,如下寫法

//先定義 常量
    public static final int SUNDAY = 0;
    public static final int MONDAY = 1;
    public static final int TUESDAY = 2;
    public static final int WEDNESDAY = 3;
    public static final int THURSDAY = 4;
    public static final int FRIDAY = 5;
    public static final int SATURDAY = 6;
    //默認參數
    @WeekDays int currentDay = SUNDAY;

    //用@IntDef "包住" 常量;
    // @Retention 定義策略
    // 聲明構造器
    @IntDef({SUNDAY, MONDAY,TUESDAY,WEDNESDAY,THURSDAY,FRIDAY,SATURDAY})
    @Retention(RetentionPolicy.SOURCE)
    public @interface WeekDays {}
    //設置參數
    public void setCurrentDay(@WeekDays int currentDay) {
        this.currentDay = currentDay;
    }

詳細文章可查看

下拉框的引用

aar包是 Android 的類庫項目的二進制發行包。

下拉框引用到別人的工程,引用方式是「arr包」


每次收穫一點點,後續還會擴展更多功能,供你們學習,支持我就Star一下「BaseRecyclerViewAdapterHelper」。

相關文章
相關標籤/搜索