RecyclerView Grid Layout 如何实现子项自适应适配屏幕显示
实现RecyclerView子项自动适配屏幕列数的方案
以下两种方案都可以实现不用手动修改列数,自动适配子项展示的需求:
方案1:动态计算列数初始化GridLayoutManager
核心逻辑是先预设子项的最小宽度,再用屏幕可用宽度除以子项最小宽度,自动得到适配的列数,适配不同尺寸屏幕、横竖屏切换场景。
- 第一步在
dimens.xml中定义子项期望的最小宽度,根据你的业务设计调整数值即可:
<dimen name="grid_item_min_width">120dp</dimen>
- 第二步编写列数计算的工具方法:
fun calculateSpanCount(context: Context, @DimenRes itemMinWidthRes: Int): Int { val displayMetrics = context.resources.displayMetrics // 扣除左右padding的屏幕可用宽度 val availableScreenWidth = displayMetrics.widthPixels - context.resources.getDimensionPixelSize(R.dimen.recycler_padding_horizontal) val itemMinWidthPx = context.resources.getDimensionPixelSize(itemMinWidthRes) // 最小取1,避免列数为0报错 return maxOf(availableScreenWidth / itemMinWidthPx, 1) }
- 第三步初始化RecyclerView时直接使用计算结果:
val spanCount = calculateSpanCount(requireContext(), R.dimen.grid_item_min_width) recyclerView.layoutManager = GridLayoutManager(requireContext(), spanCount, RecyclerView.VERTICAL, false)
方案2:使用封装后的AutoFitGridLayoutManager
可以直接复用官方开源的自动适配GridLayoutManager实现,内部自动完成列数计算:
class AutoFitGridLayoutManager : GridLayoutManager { private var mColumnWidth = 0 private var mColumnWidthChanged = true constructor(context: Context, columnWidth: Int) : super(context, 1) { setColumnWidth(columnWidth) } constructor(context: Context, columnWidth: Int, orientation: Int, reverseLayout: Boolean) : super(context, 1, orientation, reverseLayout) { setColumnWidth(columnWidth) } constructor(context: Context, attrs: AttributeSet, defStyleAttr: Int, defStyleRes: Int) : super(context, attrs, defStyleAttr, defStyleRes) { val typedArray = context.obtainStyledAttributes(attrs, intArrayOf(android.R.attr.columnWidth), defStyleAttr, defStyleRes) val columnWidth = typedArray.getDimensionPixelSize(0, -1) typedArray.recycle() setColumnWidth(columnWidth) } private fun setColumnWidth(newColumnWidth: Int) { if (newColumnWidth > 0 && newColumnWidth != mColumnWidth) { mColumnWidth = newColumnWidth mColumnWidthChanged = true } } override fun onLayoutChildren(recycler: RecyclerView.Recycler?, state: RecyclerView.State?) { if (mColumnWidthChanged && mColumnWidth > 0) { val totalSpace = if (orientation == VERTICAL) { width - paddingLeft - paddingRight } else { height - paddingTop - paddingBottom } val spanCount = maxOf(1, totalSpace / mColumnWidth) setSpanCount(spanCount) mColumnWidthChanged = false } super.onLayoutChildren(recycler, state) } }
使用时只需传入子项最小宽度的像素值即可:
val itemMinWidthPx = resources.getDimensionPixelSize(R.dimen.grid_item_min_width) recyclerView.layoutManager = AutoFitGridLayoutManager(requireContext(), itemMinWidthPx)
预期效果示意图

内容的提问来源于stack exchange,提问作者Abdulsamet Kılınçarslan
相关产品推荐
相关产品推荐

