RecyclerView实现瀑布流以及细节问题
1)使用 StaggeredGridLayoutManager
1 2 3 4 5 6 7 8 9 10
| val layoutManager = StaggeredGridLayoutManager(2, RecyclerView.VERTICAL) layoutManager.gapStrategy = StaggeredGridLayoutManager.GAP_HANDLING_NONE recyclerView.layoutManager = layoutManager
recyclerView.addItemDecoration(StaggeredDividerItemDecoration(16, true))
mAdapter = PjListVPAdapter() recyclerView.adapter = mAdapter
recyclerView.itemAnimator = DefaultItemAnimator()
|
2)如果需要Item之间的间隔,就需要自定义 ItemDecoration
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38
|
class StaggeredDividerItemDecoration( space: Int, private val includeEdge: Boolean = false ) : ItemDecoration() { private val space = TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, space.toFloat(), Resources.getSystem().displayMetrics ).toInt() override fun getItemOffsets( outRect: Rect, view: View, parent: RecyclerView, state: RecyclerView.State ) { val lp = view.layoutParams as StaggeredGridLayoutManager.LayoutParams val lm = parent.layoutManager as StaggeredGridLayoutManager val spanIndex: Int = lp.spanIndex val spanCount: Int = lm.spanCount if (includeEdge) { outRect.left = space * (spanCount - spanIndex) / spanCount outRect.right = space * (spanIndex + 1) / spanCount outRect.top = space } else { outRect.left = space * spanIndex / spanCount outRect.right = space * (spanCount - spanIndex - 1) / spanCount outRect.bottom = space } } }
|
3)滑动时闪烁,Item自动切换位置
解决方案 layoutManager.setGapStrategy(StaggeredGridLayoutManager.GAP_HANDLING_NONE)
4)设置了 GAP_HANDLING_NONE 属性之后,顶端空白
由于ViewHolder的回收机制,滑回到上方时Item需要重新自行绘制,因为item的尺寸并不确定,导致重新绘制之后跟原来的高度不一致,又禁止了左右切换的调整策略,才导致的顶端空白。通常是因为加载图片之后重新计算item高度导致,尽可能在load图片之前先确定ImageView的高度。
这个时候只能给后台同学提需求了,在服务的Json数据需要包含图片的长宽信息。
附根据屏幕计算ImageView显示的宽高
1 2 3 4 5 6 7
| private val width = (DensityUtil.getScreenWidth() - TypedValue.applyDimension( TypedValue.COMPLEX_UNIT_DIP, 68f, Resources.getSystem().displayMetrics ).toInt()) / 2 private val height = (width * 1.5).toInt() imageView.layoutParams.height = height
|
5)刷新,删除,插入同样会导致顶端空白
使用 notifyDataSetChanged()方法做刷新时,会触发StaggeredGridLayoutManager 的onItemsChanged 方法,导致item的spanIndex重现进行计算,item所在列的位置出现了变化,导致了顶部空白。
使用notifyItemRangeInserted
,notifyItemRangeChanged
做局部刷新 则不会引起变化。
6)注意item等宽问题
采用StaggeredDividerItemDecoration的等宽计算方法。