最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Android RecyclerView的Item自定義動畫及DefaultItemAnimator源碼分析

 更新時間:2016年07月10日 15:46:21   作者:Fndroid  
這篇文章主要介紹了Android RecyclerView的Item自定義動畫及DefaultItemAnimator源碼,感興趣的小伙伴們可以參考一下

這是關于RecyclerView的第二篇,說的是如何自定義Item動畫,但是請注意,本文不包含動畫的具體實現(xiàn)方法,只是告訴大家如何去自定義動畫,如何去參考源代碼。 

我們知道,RecyclerView默認會使用DefaultItemAnimator,所以如果我們需要自定義動畫,那么應該好好的讀讀這個類的源代碼,這樣不僅僅是學習怎么自定義,還要學習Android的設計模式。 

先弄明白一件事,DefaultItemAnimator繼承自SimpleItemAnimator,SimpleItemAnimator繼承自RecyclerView.ItemAnimator,所以如果需要自定義動畫,最簡單的方法是繼承SimpleItemAnimator。其次,動畫的類型有四種,分別是Add、Remove、Move以及Change,這里我們只列舉Remove,舉一反三。 

我們先看SimpleItemAnimator中的源碼,在SimpleItemAnimator中有幾個重要的方法: 

@Override
 public boolean animateDisappearance(@NonNull ViewHolder viewHolder,
   @NonNull ItemHolderInfo preLayoutInfo, @Nullable ItemHolderInfo postLayoutInfo) {
  int oldLeft = preLayoutInfo.left;
  int oldTop = preLayoutInfo.top;
  View disappearingItemView = viewHolder.itemView;
  int newLeft = postLayoutInfo == null ? disappearingItemView.getLeft() : postLayoutInfo.left;
  int newTop = postLayoutInfo == null ? disappearingItemView.getTop() : postLayoutInfo.top;
  if (!viewHolder.isRemoved() && (oldLeft != newLeft || oldTop != newTop)) {
   disappearingItemView.layout(newLeft, newTop,
     newLeft + disappearingItemView.getWidth(),
     newTop + disappearingItemView.getHeight());
   if (DEBUG) {
    Log.d(TAG, "DISAPPEARING: " + viewHolder + " with view " + disappearingItemView);
   }
   return animateMove(viewHolder, oldLeft, oldTop, newLeft, newTop);
  } else {
   if (DEBUG) {
    Log.d(TAG, "REMOVED: " + viewHolder + " with view " + disappearingItemView);
   }
   return animateRemove(viewHolder);
  }
 }

解析:這個函數(shù)是重寫RecyclerView.ItemAnimator的,接口中參數(shù)分別是ViewHolder、prelayoutInfo以及postLayoutInfo,第一個參數(shù)是指Item的ViewHolder,可以通過這個對象的itemView來獲取它的View,第二個參數(shù)是指Item刪除前的位置信息,第三個是指新的位置信息。再接下來會判斷ViewHolder是否已經(jīng)被移除以及位置是否發(fā)生變化,然后在調(diào)用animateRemove這個抽象方法,如果我們要自定義動畫,就需要去實現(xiàn)它(回調(diào)思想)。

 public final void dispatchRemoveStarting(ViewHolder item) {
   onRemoveStarting(item);
 } 
public void onRemoveStarting(ViewHolder item) {
 } 

解析:dispatchRemoveStaring個是一個final方法,也就是不能被重寫,如果我們需要處理一些在Remove開始的時候的邏輯,我們就需要在animateRemove方法中調(diào)用這個方法,這個方法會執(zhí)行一個onRemoveStaring方法,這個方法就允許我們重寫,所以邏輯應該寫在onRemoveStaring中,當我們調(diào)用dispatchRemoveStaring的時候,onRemoveStaring就會被執(zhí)行。 

這里只說了兩個,但是,加上其他動作的就不只是兩個啦。。。
所以,當我們繼承了SimpleItemAnimator的時候,需要實現(xiàn)里面的一些方法,一般有如下這些: 
 ① animateRemove(Add、Move和Change):這些方法會在動畫發(fā)生的時候回調(diào),一般會在這個方法中用列表記錄每個Item的動畫以及屬性
 ② endAnimation、endAnimations:分別是在一個Item或是多個Item需要立即停止的時候回調(diào)
 ③ isRunning:如果需要順暢滑動的時候,必須要重寫這個方法,很多時候比如在網(wǎng)絡加載的時候滑動卡頓就是這個方法邏輯不對
 ④ run'PendingAnimations:這是最重要的一個方法。因為animateDisappearence等方法返回的是animateRemove等方法返回的值,而這個方法則是根據(jù)這些值來確定是否有準備好的動畫需要播放,如果有,就會回調(diào)這個方法。在這個方法我們需要處理每一個動作(Remove、Add、Move以及Change)的動畫
 

所以,我們的一般步驟就是:
 ①創(chuàng)建一個SimpleItemAnimator的子類
 ②創(chuàng)建每個動作的動作列表
 ③重寫animateRemove等方法,當界面中有動作發(fā)生,這些函數(shù)會被回調(diào),這里進行記錄并返回true使得run'PendingAnimations開始執(zhí)行
 ④重寫run'PendingAnimations,當③的方法返回true的時候,就認為需要執(zhí)行動畫,我們需要把動畫執(zhí)行的邏輯寫在這里面
 ⑤重寫isRunning,提供動畫播放狀態(tài),一般是返回動作列表是否為空
 ⑥如果有需要,重寫endAnimation、endAnimations、onRemoveFinish等方法
具體的步驟有了,但是我們還不清楚該怎么構建它,不用著急,為了方便我們,谷歌其實已經(jīng)提供了DefaultItemAnimator,我們可以參考一些它的源碼,沒有人講的比源碼有道理,我們需要的是有足夠的耐心!
DefaultItemAnimator中定義了一些ArrayList來存放動作的信息,如下:

 private ArrayList<ViewHolder> mPendingRemovals = new ArrayList<>();
private ArrayList<ViewHolder> mRemoveAnimations = new ArrayList<>();


@Override
 public boolean animateRemove(final ViewHolder holder) {
  resetAnimation(holder);
  mPendingRemovals.add(holder);
  return true;
 }

解析:可以看到animatorRemove方法直接是把viewholder加入列表中,然后返回true 

@Override
 public void runPendingAnimations() {
  boolean removalsPending = !mPendingRemovals.isEmpty();
  boolean movesPending = !mPendingMoves.isEmpty();
  boolean changesPending = !mPendingChanges.isEmpty();
  boolean additionsPending = !mPendingAdditions.isEmpty();
  if (!removalsPending && !movesPending && !additionsPending && !changesPending) {
   // nothing to animate
   return;
  }
  // First, remove stuff
  for (ViewHolder holder : mPendingRemovals) {
   animateRemoveImpl(holder);
  }
  mPendingRemovals.clear();
  // Next, move stuff
  ......
  // Next, change stuff, to run in parallel with move animations
  ......
  // Next, add stuff
  ......
 }

解析:根據(jù)上面可以知道,runPendingAnimations會執(zhí)行,可看到,在這個方法中遍歷了動作列表,并讓每個Item都執(zhí)行了animatorRemoveImpl方法,其他動作的方法暫時先省略,有興趣的可以自行閱讀。 

private void animateRemoveImpl(final ViewHolder holder) {
  final View view = holder.itemView;
  final ViewPropertyAnimatorCompat animation = ViewCompat.animate(view);
  mRemoveAnimations.add(holder);
  animation.setDuration(getRemoveDuration())
    .alpha(0).setListener(new VpaListenerAdapter() {
   @Override
   public void onAnimationStart(View view) {
    dispatchRemoveStarting(holder);
   }

   @Override
   public void onAnimationEnd(View view) {
    animation.setListener(null);
    ViewCompat.setAlpha(view, 1);
    dispatchRemoveFinished(holder);
    mRemoveAnimations.remove(holder);
    dispatchFinishedWhenDone();
   }
  }).start();
 }

解析:可以看到animatorRemoveImpl方法中實現(xiàn)了整個動畫的具體邏輯,具體怎么做不在本文范圍中,在我們執(zhí)行了動畫之后,也就是在動畫的Listener中的onAnimatorEnd中調(diào)用了dispatchRemoveFinish,還記得這個方法嗎,它會執(zhí)行onRemoveFinish方法,onRemoveFinish方法是可以供給我們重寫的。然后把item移除動作列表。 

@Override
 public boolean isRunning() {
  return (!mPendingAdditions.isEmpty() ||
    !mPendingChanges.isEmpty() ||
    !mPendingMoves.isEmpty() ||
    !mPendingRemovals.isEmpty() ||
    !mMoveAnimations.isEmpty() ||
    !mRemoveAnimations.isEmpty() ||
    !mAddAnimations.isEmpty() ||
    !mChangeAnimations.isEmpty() ||
    !mMovesList.isEmpty() ||
    !mAdditionsList.isEmpty() ||
    !mChangesList.isEmpty());
 }

解析:isRunning方法其實就是根據(jù)動作列表是否為空來返回結果
還有其他一些函數(shù)可以自己閱讀源代碼。

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • Android 列表形式的切換的示例代碼

    Android 列表形式的切換的示例代碼

    本篇文章主要介紹了Android 列表形式的切換的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-09-09
  • 手把手教你實現(xiàn)Android編譯期注解

    手把手教你實現(xiàn)Android編譯期注解

    今天給大家介紹Android編譯期注解sdk的步驟以及注意事項,并簡要分析了運行時注解以及字節(jié)碼技術在生成代碼上與編譯期注解的不同與優(yōu)劣,感興趣的朋友一起看看吧
    2021-07-07
  • Android基礎之使用Fragment控制切換多個頁面

    Android基礎之使用Fragment控制切換多個頁面

    Android官方已經(jīng)提供了Fragment的各種使用的Demo例子,在我們SDK下面的API Demo里面就包含了Fragment的各種使用例子,需要看Demo的朋友,直接看API Demo那個程序就可以了,不用到處去找。里面分開不同功能,實現(xiàn)了不同的類
    2013-07-07
  • Android自定義viewgroup快速滑動(4)

    Android自定義viewgroup快速滑動(4)

    這篇文章主要為大家詳細介紹了Android自定義viewgroup快速滑動的相關資料,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-12-12
  • FFmpeg?Principle學習new_video_stream添加視頻輸出流

    FFmpeg?Principle學習new_video_stream添加視頻輸出流

    這篇文章主要為大家介紹了FFmpeg?Principle學習new_video_stream添加視頻輸出流示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-10-10
  • Android實現(xiàn)簡單購物車

    Android實現(xiàn)簡單購物車

    這篇文章主要為大家詳細介紹了Android實現(xiàn)簡單購物車,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-06-06
  • Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果示例

    Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果示例

    這篇文章主要介紹了Android開發(fā)實現(xiàn)的圓角按鈕、文字陰影按鈕效果,涉及Android界面布局與屬性設置相關操作技巧,需要的朋友可以參考下
    2019-04-04
  • android實現(xiàn)人臉識別技術的示例代碼

    android實現(xiàn)人臉識別技術的示例代碼

    本篇文章主要介紹了android人臉識別技術的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • Android實現(xiàn)畫板功能(二)

    Android實現(xiàn)畫板功能(二)

    這篇文章主要為大家詳細介紹了Android實現(xiàn)畫板功能的第二篇,使用imageView,bitmap方式實現(xiàn)畫板,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2021-05-05
  • Android自定義控件下拉刷新實例代碼

    Android自定義控件下拉刷新實例代碼

    這篇文章主要介紹了Android自定義控件下拉刷新實例代碼的相關資料,需要的朋友可以參考下
    2016-10-10

最新評論

西乌| 青铜峡市| 洛隆县| 台东市| 大余县| 华容县| 新丰县| 铅山县| 嵊州市| 乌拉特前旗| 黄浦区| 靖远县| 苍溪县| 宾川县| 奉节县| 安远县| 汉中市| 武穴市| 隆林| 遂平县| 成安县| 英德市| 浮山县| 永善县| 栖霞市| 德格县| 凌云县| 松滋市| 兴义市| 西盟| 郧西县| 蕉岭县| 红河县| 延边| 德清县| 巨野县| 云安县| 谢通门县| 佛学| 灵丘县| 读书|