You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.05 02:54:03