Android GridLayout如何为底部行设置不同列宽?
如何实现多行列宽比例不同的网格布局
其实你遇到的问题是GridLayout的layout_columnWeight特性导致的——它是作用于整个列的全局权重,所以你给上面行设置的1:2比例会被所有行继承,最后一行自然没法变成1:1的等宽。
能不能用GridLayout实现?
可以,但实现起来比较绕,因为GridLayout的列宽度大概率是全局统一的,要让最后一行突破这个限制,需要给底部行的控件单独设置布局属性:
修改后的GridLayout代码示例:
<?xml version="1.0" encoding="utf-8"?> <android.widget.GridLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:columnCount="2" android:rowCount="5" tools:context=".MainActivity"> <!-- 第1-4行:左列1份权重,右列2份权重 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="2" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="2" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="2" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="2" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="2" android:layout_rowWeight="2" android:text="TextView"/> <!-- 底部行:通过layout_gravity和权重强制等宽 --> <Spinner android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="1" android:layout_gravity="fill_horizontal" android:hint="Spinner"/> <Spinner android:layout_width="0dp" android:layout_height="0dp" android:layout_columnWeight="1" android:layout_rowWeight="1" android:layout_gravity="fill_horizontal" android:hint="Spinner"/> </android.widget.GridLayout>
不过这种方式有时候会因为GridLayout的全局列权重优先级问题,导致底部行的等宽效果不稳定,所以更推荐下面两种更可靠的方案。
更推荐的实现方式
1. LinearLayout嵌套(直观易维护)
这种方式逻辑最清晰,外层用垂直LinearLayout,每一行用水平LinearLayout控制列宽比例,完全避免GridLayout的全局权重限制:
<?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:orientation="vertical" tools:context=".MainActivity"> <!-- 第1行:权重2,列宽1:2 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:text="TextView"/> </LinearLayout> <!-- 第2行:权重2,列宽1:2 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:text="TextView"/> </LinearLayout> <!-- 第3行:权重2,列宽1:2 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:text="TextView"/> </LinearLayout> <!-- 第4行:权重2,列宽1:2 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="2" android:orientation="horizontal"> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:text="TextView"/> <TextView android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="2" android:text="TextView"/> </LinearLayout> <!-- 底部行:权重1,列宽1:1 --> <LinearLayout android:layout_width="match_parent" android:layout_height="0dp" android:layout_weight="1" android:orientation="horizontal"> <Spinner android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:hint="Spinner"/> <Spinner android:layout_width="0dp" android:layout_height="match_parent" android:layout_weight="1" android:hint="Spinner"/> </LinearLayout> </LinearLayout>
2. ConstraintLayout(灵活扁平化)
如果你的布局需要更复杂的交互或者想避免嵌套,ConstraintLayout是最佳选择,通过指引线(Guideline)可以轻松实现不同行的列宽比例:
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:app="http://schemas.android.com/apk/res-auto" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" tools:context=".MainActivity"> <!-- 上面4行的垂直指引线(1:2分割) --> <androidx.constraintlayout.widget.Guideline android:id="@+id/above_rows_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.333"/> <!-- 底部行的垂直指引I线(1:1分害) --> <androidx.constraintlayout.widget.Guideline android:id="@+id/bottom_row_guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.5"/> <!-- 米平把引线,设置行高比例:上面4行行占2份,底部行占1份 --> <androidx.constraintlayout.widget.Guideline android:id="@+id/row1_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.222"/> <androidx.constraintlayout.widget.Guideline android:id="@+id/row2_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.444"/> <androidx.constraintlayout.widget.Guideline android:id="@+id/row3_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.666"/> <androidx.constraintlayout.widget.Guideline android:id="@+id/row4_bottom" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.888"/> <!-- 第1行左 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/above_rows_guideline" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/row1_bottom"/> <!-- 第1行右 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toRightOf="@id/above_rows_guideline" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintBottom_toTopOf="@id/row1_bottom"/> <!-- 第2行左 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/above_rows_guideline" app:layout_constraintTop_toBottomOf="@id/row1_bottom" app:layout_constraintBottom_toTopOf="@id/row2_bottom"/> <!-- 第2行右 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toRightOf="@id/above_rows_guideline" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/row1_bottom" app:layout_constraintBottom_toTopOf="@id/row2_bottom"/> <!-- 第3行左 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/above_rows_guideline" app:layout_constraintTop_toBottomOf="@id/row2_bottom" app:layout_constraintBottom_toTopOf="@id/row3_bottom"/> <!-- 第3行右 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toRightOf="@id/above_rows_guideline" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/row2_bottom" app:layout_constraintBottom_toTopOf="@id/row3_bottom"/> <!-- 第4行左 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/above_rows_guideline" app:layout_constraintTop_toBottomOf="@id/row3_bottom" app:layout_constraintBottom_toTopOf="@id/row4_bottom"/> <!-- 第4行右 --> <TextView android:layout_width="0dp" android:layout_height="0dp" android:text="TextView" app:layout_constraintLeft_toRightOf="@id/above_rows_guideline" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toBottomOf="@id/row3_bottom" app:layout_constraintBottom_toTopOf="@id/row4_bottom"/> <!-- 底部行左Spinner --> <Spinner android:id="@+id/sp1" android:layout_width="0dp" android:layout_height="0dp" android:hint="Spinner" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@id/bottom_row_guideline" app:layout_constraintTop_toBottomOf="@id/row4_bottom" app:layout_constraintBottom_toBottomOf="parent"/> <!-- 底部行右Spinner --> <Spinner android:layout_width="0dp" android:layout_height="0dp" android:hint="Spinner" app:layout_constraintLeft_toRightOf="@id/bottom_row_guideline" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@id/sp1" app:layout_constraintBottom_toBottomOf="@id/sp1"/> </androidx.constraintlayout.widget.ConstraintLayout>
总的来说,GridLayout可以实现你的需求,但不够灵活和直观;LinearLayout嵌套是最容易上手和维护的方案;ConstraintLayout则适合追求布局扁平化和复杂交互的场景,你可以根据自己的需求选择。
内容的提问来源于stack exchange,提问作者coray8
相关产品推荐
相关产品推荐

