如何实现占满屏幕宽度的2x2正方形CardView网格布局?
实现2x2网格中CardView的正方形布局
要解决CardView被拉伸、无法保持正方形的问题,有几种简单可靠的方案,根据你的布局结构选择即可:
方案一:自定义SquareCardView(最通用)
这种方法不管你用GridLayout、RecyclerView还是其他布局都能生效,核心是让CardView的高度强制等于宽度:
- 创建自定义CardView类:
import android.content.Context import android.util.AttributeSet import androidx.cardview.widget.CardView class SquareCardView @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = 0 ) : CardView(context, attrs, defStyleAttr) { override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) { // 让高度测量规格和宽度一致,实现正方形 super.onMeasure(widthMeasureSpec, widthMeasureSpec) } }
- 在XML布局中替换原CardView为这个自定义View:
假设你的GridLayout是2列布局,给每个SquareCardView设置layout_width="0dp"和layout_columnWeight="1"(让每列平分父容器宽度),高度设为wrap_content即可:
<GridLayout android:layout_width="match_parent" android:layout_height="wrap_content" android:columnCount="2" android:rowCount="2"> <com.your.package.name.SquareCardView android:layout_width="0dp" android:layout_height="wrap_content" android:layout_columnWeight="1" android:layout_margin="8dp" app:cardCornerRadius="8dp" app:cardElevation="4dp"/> <!-- 重复另外3个SquareCardView --> </GridLayout>
方案二:用ConstraintLayout设置宽高比(无需自定义View)
如果你的布局可以改用ConstraintLayout实现2x2网格,或者给每个CardView套一层ConstraintLayout,直接通过属性设置宽高比为1:1:
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="match_parent"> <!-- 第一个CardView --> <androidx.cardview.widget.CardView android:id="@+id/card1" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="8dp" app:cardCornerRadius="8dp" app:cardElevation="4dp" app:layout_constraintWidth_percent="0.45" app:layout_constraintHeight_toEqualWidth="true" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"/> <!-- 第二个CardView --> <androidx.cardview.widget.CardView android:id="@+id/card2" android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="8dp" app:cardCornerRadius="8dp" app:cardElevation="4dp" app:layout_constraintWidth_percent="0.45" app:layout_constraintHeight_toEqualWidth="true" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent"/> <!-- 第三个和第四个同理,设置顶部约束为card1/card2的底部 --> </androidx.constraintlayout.widget.ConstraintLayout>
这里用layout_constraintWidth_percent="0.45"让每个CardView占父宽度的45%(留出门距),再通过layout_constraintHeight_toEqualWidth="true"强制高度等于宽度,完美实现正方形。
方案三:RecyclerView + GridLayoutManager(适合动态数据)
如果你的2x2网格是动态生成的(比如从数据源加载),用RecyclerView配合GridLayoutManager更合适:
- 设置RecyclerView的LayoutManager:
recyclerView.layoutManager = GridLayoutManager(context, 2)
- 在Item布局中,给CardView套一层ConstraintLayout,设置宽高比1:1:
<androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <androidx.cardview.widget.CardView android:layout_width="0dp" android:layout_height="0dp" android:layout_margin="8dp" app:cardCornerRadius="8dp" app:cardElevation="4dp" app:layout_constraintWidth_toMatchParent="true" app:layout_constraintHeight_toEqualWidth="true"/> </androidx.constraintlayout.widget.ConstraintLayout>
这样每个Item的CardView会自动保持正方形,宽度平分RecyclerView的宽度。
内容的提问来源于stack exchange,提问作者Jonas




