RecyclerView+PageSnapHelper實現ViewPager效果+自動翻頁


預期效果是大多app都會用到的首頁頂部圖片banner,3s自動輪播,也可手動切換

用法很簡單,做attach就好(以下為kotlin代碼)

recyclerView.layoutManager = LinearLayoutManager(context, LinearLayoutManager.HORIZONTAL, false)
val snapHelper = PagerSnapHelper()
snapHelper.attachToRecyclerView(recyclerView)

自動翻頁是定義的handler每3s執行一次bannerPos++然后recyclerView滾動,但是注意滾動的方法要使用

recyclerView.smoothScrollToPosition(bannerPos)

使用的話scrollToPosition()就不會有左右平滑的效果

如果需要同步更新Indicator,在recyclerView的滑動監聽里

recyclerView.addOnScrollListener(object : RecyclerView.OnScrollListener() {
                    override fun onScrollStateChanged(recycler: RecyclerView, newState: Int) {
                        super.onScrollStateChanged(recycler, newState)
                        when (newState) {
                            RecyclerView.SCROLL_STATE_IDLE -> {
                                val viewIdle = snapHelper.findSnapView(recyclerView.layoutManager)
                                if (viewIdle != null) {
                                    val pos = recyclerView.layoutManager?.getPosition(viewIdle) ?: 0
                                    updateIndicators(pos)
                                }
                            }
                        }
                    }
                })
  /**
     * 更新到當前指示器
     */
    private fun updateIndicators(position: Int) {
        for (i in 0 until indicatorContainer.childCount) {
            val childView = indicatorContainer.getChildAt(i)
            childView.background = if (position == i)
               resources.getDrawable(R.drawable.shape_indicator_orange)
            else
               resources.getDrawable(R.drawable.shape_indicator_gray)
        }
    }

補充一下indicator的初始化方法

private fun setIndicators(bannerList: List<String>?) {
        //只有一頁的時候不顯示指示器
        if (bannerList?.size ?: 0 <= 1) {
            return
        }
        indicatorContainer.removeAllViews()
        for (i in bannerList!!.indices) {
            val indicatorView = View(context)
            indicatorView.background = resources.getDrawable(R.drawable.shape_indicator_gray)
            val layoutParams: LinearLayout.LayoutParams = LinearLayout.LayoutParams(
                ConvertUtils.dp2px(6f), ConvertUtils.dp2px(6f)
            )
            if (i != 0) layoutParams.leftMargin = ConvertUtils.dp2px(8f)
            indicatorView.layoutParams = layoutParams
            indicatorContainer.addView(indicatorView)
        }
        updateIndicators(indicatorContainer, 0)
    }

 

我這里把整個頁面都用一個recyclerView展示的,所以頂部banner也作為一個item嵌在數據里(感覺還是addHeader方法合理哈),嵌套在里面要更新呢就更新adapter,當時發現自動翻頁時滑動起來有重復頁面閃過的情況,這是因為adapter做notify的時候每次都重置到了第一頁再調用前面說的smooth方法滑動,所以中間頁面會展示出快速划過。

所以我在調用smooth滑動之前先把banner用scrollToPosition()方法無痕跡滑動到前一張,這樣就看不出閃頁了

if (bannerPos > 0){
    recyclerView.scrollToPosition(bannerPos-1)
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM