使用 RecyclerView 實(shí)現(xiàn)輪播圖

之前總結(jié)了實(shí)現(xiàn)輪播圖的各種方式.不過總的來說,基本都是通過viewpager來實(shí)現(xiàn).并且效果也不能稱為 完美 . 在IOS中,實(shí)現(xiàn)輪播圖的方式更為豐富,什么兩圖輪播,三圖輪播... 所以偶爾我也思考是否還有其它方式可以實(shí)現(xiàn).

Google官方提供的可滑動控件無非就是ScrollView,ListView,RecyclerView等等. 其中RecyclerView就是專門處理視圖回收的,那么是否可以使用RecyclerView來實(shí)現(xiàn)呢?

使用RecyclerView來輪播,首先需要解決兩個問題

  • 一次只能滑動一頁
  • 不能滑一半,每次停止的時候,都要讓當(dāng)前頁居中顯示

本來要實(shí)現(xiàn)這個功能是挺麻煩的,幸好在 RecyclerView-24.2.0(大概是)開始,新增了一個類可以幫助我們完成90%,那就是 LinearSnapHelper.

LinearSnapHelper的使用很簡單:

new LinearSnapHelper().attachToRecyclerView(recyclerView);

只需要上面這行代碼,RecyclerView就能實(shí)現(xiàn)類似ViewPager的功能,在滑動停止的時候,讓某頁居中顯示.唯一的不同,就是RecyclerView一次可以滑動很多頁.
其實(shí)這樣就已經(jīng)完全足夠了,當(dāng)然如果你一定想每次都只能滑動一頁,那么就需要重寫一下 LinearSnapHelper 的 findTargetSnapPosition 方法. findTargetSnapPosition 就是 LinearSnapHelper 通過當(dāng)前滑動速度,計算最終定位position的方法.

private class PagerSnapHelper extends LinearSnapHelper {    
     @Override    
     public int findTargetSnapPosition(RecyclerView.LayoutManager layoutManager, int velocityX, int velocityY) {        
        int targetPos = super.findTargetSnapPosition(layoutManager, velocityX, velocityY);        
        final View currentView = findSnapView(layoutManager);        
        if(targetPos != RecyclerView.NO_POSITION && currentView != null){            
           int currentPostion = layoutManager.getPosition(currentView);            
           int first = ((LinearLayoutManager)layoutManager).findFirstVisibleItemPosition();            
           int last = ((LinearLayoutManager)layoutManager).findLastVisibleItemPosition();           
           currentPostion = targetPos < currentPostion ? last : (targetPos > currentPostion ? first : currentPostion);            
           targetPos = targetPos < currentPostion ? currentPostion - 1 : (targetPos > currentPostion ? currentPostion + 1 : currentPostion);        
         }        
        return targetPos;    
     }
}

在上面的代碼中,稍微耍了點(diǎn)小心思,就是通過原來計算的結(jié)果,如果是往前滑動,那么就重新賦值為當(dāng)前位置 - 1 ; 如果是往后滑動,那就則重新賦值為當(dāng)前位置 + 1. 到這里,RecyclerView的效果就完全和ViewPager一致了.

因?yàn)镽ecyclerView內(nèi)部完美的處理了視圖的回收,所以實(shí)現(xiàn)輪播圖的思路也就很明確了:

  1. 給適配器設(shè)置為無限大,

  2. 然后將初始位置通過 scrollToPosition() 定位在中間某個地方,完全不用擔(dān)心像使用ViewPager一樣的ANR問題,

  3. 通過定時器,每隔一定事件調(diào)用

    // 向后翻動一頁 
    recyclerView.smoothScrollToPosition(++currentIndex);
    
  4. 刷新的時候,通過 notifyDataSetChanged()更新數(shù)據(jù),不用每次再重新設(shè)置適配器了.

其它的思路,就和 全面總結(jié)輪播圖 中的最終方式一樣了,這里不再重復(fù).
效果也和之前非常類似:

S61023-153210.jpg

代碼在這里

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容