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

RecyclerView网格单元格自动适配屏幕宽度问题求助

解决RecyclerView实现正方形网格的方案

方案一:纯XML布局实现(最省心)

先修改你的item布局,原来的CardView直接放在DataBinding根标签下,导致比例约束失效,得加个ConstraintLayout当容器:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.constraintlayout.widget.ConstraintLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

        <androidx.cardview.widget.CardView
            android:layout_width="match_parent"
            android:layout_height="0dp"
            app:layout_constraintDimensionRatio="1:1"
            android:clickable="true"
            app:cardUseCompatPadding="false"
            app:cardPreventCornerOverlap="false">

            <TextView
                android:id="@+id/itemElevation"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:gravity="center"
                android:textColor="@android:color/black"
                app:elevationItem="@{item}"
                tools:text="33"
                tools:background="@android:color/holo_orange_dark"/>

        </androidx.cardview.widget.CardView>

    </androidx.constraintlayout.widget.ConstraintLayout>

</layout>
  • 加ConstraintLayout是为了让layout_constraintDimensionRatio生效,CardView高度设为0dp,靠比例自动和宽度一致,实现正方形
  • 删掉TextView的固定宽高,改成match_parent,让它填满CardView
  • 开启cardUseCompatPadding和cardPreventCornerOverlap是为了去掉CardView自带的多余空隙,确保单元格无缝衔接

RecyclerView的XML不用大改,只要保证它是match_parent宽高,spanCount可以随便改,改完单元格会自动适配宽度并保持正方形。

方案二:代码动态算尺寸

不想改布局结构的话,直接在Adapter里动态设置item高度:

第一步:修改item布局

把CardView宽度设为match_parent,TextView改成填满父容器:

<layout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto">

    <androidx.cardview.widget.CardView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:clickable="true">

        <TextView
            android:id="@+id/itemElevation"
            android:layout_width="match_parent"
            android:layout_height="match_parent"
            android:gravity="center"
            android:textColor="@android:color/black"
            app:elevationItem="@{item}"
            tools:text="33"
            tools:background="@android:color/holo_orange_dark"/>

    </androidx.cardview.widget.CardView>

</layout>

第二步:在Adapter里设置高度

在onCreateViewHolder里算出每个item的宽度(RecyclerView宽度除以列数),再把高度设成和宽度一样:

class YourAdapter(private val spanCount: Int) : RecyclerView.Adapter<YourAdapter.ViewHolder>() {

    override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
        val inflater = LayoutInflater.from(parent.context)
        val binding = ItemCellBinding.inflate(inflater, parent, false)
        
        // 计算每个item的宽度,直接用父容器宽度除以列数
        val itemWidth = parent.width / spanCount
        // 强制高度等于宽度,实现正方形
        binding.root.layoutParams.height = itemWidth
        
        return ViewHolder(binding)
    }

    // 其他必要方法...
}

如果RecyclerView初始化时还没测好宽度,parent.width可能为0,那就加个监听,等布局完成后再刷新:

gridView.viewTreeObserver.addOnGlobalLayoutListener(object : ViewTreeObserver.OnGlobalLayoutListener {
    override fun onGlobalLayout() {
        gridView.viewTreeObserver.removeOnGlobalLayoutListener(this)
        // 刷新Adapter让尺寸生效
        adapter.notifyDataSetChanged()
    }
})

重点提醒

  • 绝对不能给单元格里的控件设固定宽高,不然肯定会有空隙或者适配不了列数变化
  • CardView自带的padding容易被忽略,要关掉那些默认的padding属性

内容的提问来源于stack exchange,提问作者Seb

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:12:32