Android技巧:学习使用GridLayout

GridLayout是一个非常强大的网格类布局,它不但能像TableLayout那样,实现网格类布局,但它更为强大的地方在于每个Cell的大小可以横向或者纵向拉伸,每个Cell的对齐方式也有很多种,而且不像TableLayout,需要一个TableRow,GridLayout可以通过指定Cell的坐标位置就能实现Cell的拉伸,从而实现,大小不一致的风格卡片式布局。

基本概念

GridLayout把页面分成m行和n列,使用m+1条线和n+1条线,把页面共分成n*m个Cell。指定位置时行坐标是从0到m,列坐标是从0到n。每一个子View占一个或多个Cell。比如(0, 0)到(0, 1)就是占第一个Cell的区域。(0, 0), (0, 2)就是占第一行的2个Cell的区域(横向拉伸).

使用方法

主要介绍一下如何添加Cell,以及设置Cell的位置和拉伸。其他的跟普通的ViewGroup没什么区别的,也没啥好说的。

GridLayout的基本设置

首先需要给GridLayout设置行数和列数:

  • android:columnCount 整数,最多的列数
  • android:rowCount 整数,最多的行数

在添加Cell就需要注意,不能超过设置的最大行数和列数,否则在添加Cell时会有异常。

元素Cell的位置控制

添加Cell时需要指定其位置

  • android:layout_column 整数n,在哪一列开始显示n=[0, 最大列-1]
  • android:layout_columnSpan 整数k,指定元素横跨几列,需要注意保证n+k <= 最大列数
  • android:layout_row 指定从哪一行开始显示,规则同列数
  • android:layout_rowSpan 纵向跨几行,规则同列

行高和列宽的确定

每一行的高度是由这一行中Cell的最大高度决定的,以及每一列的宽度是由每一列中最大的宽度决定的,小于行高和列宽的元素可以设置其对齐方式和填充方式。

填充方式

通过Cell的android:layout_gravity参数来指定,Cell的填充方式,注意仅当Cell元素本身的尺寸小于它所占格子的大小时才有效,比如元素本身尺寸小于行高和列宽,或者当它占多行,或者占多列时:

  • center -- 不改变元素的大小,仅居中
  • center_horizontal -- 不改变大小,水平居中
  • center_vertical -- 不改变大小,垂直居中
  • top -- 不改变大小,置于顶部
  • left -- 不改变大小,置于左边
  • bottom -- 不改变大小,置于底部
  • right -- 不改变大小,置于右边
  • start -- 不改变大小,置于开头(这个是与RTL从右向左读的文字有关的,如果使用start/end,那么当LTR文字时start=left,end=right,当RTL时start=right,end=left,也就是说系统会自动处理了)
  • end -- 不改变大小,置于结尾
  • fill -- 拉伸元素控件,填满其应该所占的格子
  • fill_vertical -- 仅垂直方向上拉伸填充
  • fill_horizontal -- 仅水平方向上拉伸填充
  • clip_vertical -- 垂直方向上裁剪元素,仅当元素大小超过格子的空间时
  • clip_horizontal -- 水平方向上裁剪元素,仅当元素大小超过格子的空间时

需要注意的是这些值是可以组合的,比如:

xml 复制代码
android:layout_gravity="center_vertical|clip_horizontal"

Cell之间的间距如何控制

默认间距

可以使用默认的间距android:useDefaultMargins="true"或者GridLayout#setUseDefaultMargins()。这个属性默认值是"false"。

另外一种方式就是跟普通布局管理器一样,给每个Cell设置其margins

通常如果不满意系统的默认间距,就可以设置useDefaultMargins="false",然后通过给Cell设置margin来控制间距。

居中方法

  • 仅有一个Cell或者仅有一行,或者仅有一列时

    当仅有一个子View时或者仅有一行或者一列的时候,可以把每个Cell设置其android:layout_gravitiy="center"(相应代码为LayoutParams#GravityCENTER),就可以让其在GridLayout中居中。

让一行居中:

xml 复制代码
    <GridLayout
        android:layout_width="wrap_content"
        android:layout_height="200dip"
        android:useDefaultMargins="true"
        android:background="@android:color/white"
        android:rowCount="1"
        android:columnCount="2">
        <Button android:layout_column="0"
            android:layout_row="0"
            android:text="Left Button"
            android:layout_gravity="fill_horizontal|center_vertical"/>
        <Button android:layout_column="1"
            android:layout_row="0"
            android:text="Right Button"
            android:layout_gravity="fill_horizontal|center_vertical"/>
    </GridLayout>
让一个元素居中:
xml 复制代码
    <GridLayout
        android:layout_width="200dip"
        android:layout_height="200dip"
        android:useDefaultMargins="true"
        android:background="@android:color/white"
        android:rowCount="1"
        android:columnCount="1">
        <Button android:layout_column="0"
            android:layout_row="0"
            android:text="Left Button"
            android:layout_gravity="center"/>
    </GridLayout>
  • 其他情况

    其他情况,设置子View的Gravity就不再起作用了,这时最好的办法就是让GridLayout的高度是WRAP_CONTENT,然后让GridLayout在其父布局中居中。

xml 复制代码
     <LinearLayout
        android:layout_width="match_parent"
        android:orientation="vertical"
        android:gravity="center"
        android:background="@android:color/darker_gray"
        android:layout_height="200dip">
        <GridLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center"
            android:useDefaultMargins="true"
            android:background="@android:color/white"
            android:rowCount="2"
            android:columnCount="2">
            <Button android:layout_column="0"
                android:layout_row="0"
                android:text="Left Button"
                android:layout_gravity="fill_horizontal|center_vertical"/>
            <Button android:layout_column="1"
                android:layout_row="0"
                android:text="Right Button"
                android:layout_gravity="fill_horizontal|center_vertical"/>
            <Button android:layout_column="1"
                android:layout_row="1"
                android:text="Right Button 2"
                android:layout_gravity="fill_horizontal|center_vertical"/>
        </GridLayout>
    </LinearLayout>

适用场景

GridLayout虽然强大,可以当作LinearLayout使用,也可以当作RelativeLayout使用,甚至也能当FrameLayout使用。但是,我们不可以滥用,对于任意布局都一样,不能是它能实现需求就使用它,而是要根据实际的需求,选择最简单,最方便的,同时也要考虑性能。

通常对于类似于网格的布局就可以考虑用GridLayout来实现,或者用LinearLayout横七竖八的套了好几层时也要考虑使用GridLayout。

GridLayout vs GridView or RecyclerView

当要实现网格布局,或者非均匀风格布局时,可能首先想到的就是GridView,但是这也要看实际的情况而定。GridView,ListView以及RecyclerView是用于无限长度列表或者网格的场景,它们最大的特点是无限长度,因此这几个组件的重点在于如何复用Cell以提升性能,以及处理手势事件(Fling)等。所以,每当遇到列表或者网格的时候,先想一下这个长度大概会是多少,如果是在百个以内,且不会随时增长,这时就可以考虑使用静态(非动态复用)的组件比如LinearLayout或者GridLayout来实现。

实例

说的太多都是废话,来一个实例感觉一下子是最直接的:

xml 复制代码
<GridLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_centerInParent="true"
            android:background="@android:color/white"
            android:alignmentMode="alignMargins"
            android:useDefaultMargins="true"
            android:columnCount="4"
            android:rowCount="5"
            android:visibility="visible">
            <Button android:layout_column="0"
                android:layout_row="0"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="1"/>
            <Button android:layout_column="1"
                android:layout_row="0"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="2"/>
            <Button android:layout_column="2"
                android:layout_row="0"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="3"/>
            <Button android:layout_column="0"
                android:layout_row="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="4"/>
            <Button android:layout_column="1"
                android:layout_row="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="5"/>
            <Button android:layout_column="2"
                android:layout_row="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="6"/>
            <Button android:layout_column="0"
                android:layout_row="2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="7"/>
            <Button android:layout_column="1"
                android:layout_row="2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="8"/>
            <Button android:layout_column="2"
                android:layout_row="2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="9"/>
            <Button android:layout_column="0"
                android:layout_row="3"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="0"/>
            <Button android:layout_column="1"
                android:layout_row="3"
                android:layout_gravity="fill_horizontal"
                android:layout_columnSpan="2"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="Delete"/>
            <Button android:layout_column="0"
                android:layout_row="4"
                android:layout_columnSpan="2"
                android:layout_gravity="fill_horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="Clear"/>
            <Button android:layout_column="2"
                android:layout_row="4"
                android:layout_columnSpan="2"
                android:layout_gravity="fill_horizontal"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="="/>
            <Button android:layout_column="3"
                android:layout_row="0"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="fill"
                android:padding="10dip"
                android:text="+"/>
            <Button android:layout_column="3"
                android:layout_row="1"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="fill"
                android:padding="10dip"
                android:text="-"/>
            <Button android:layout_column="3"
                android:layout_row="2"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_gravity="fill"
                android:padding="10dip"
                android:text="*"/>
            <Button android:layout_column="3"
                android:layout_row="3"
                android:layout_columnSpan="1"
                android:layout_gravity="fill"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:padding="10dip"
                android:text="/"/>
        </GridLayout>

参考资料

欢迎搜索并关注 公众号「稀有猿诉」 获取更多的优质文章!

保护原创,请勿转载!

相关推荐
津津有味道5 小时前
Android Studio创建新项目并引入第三方so外部aar库驱动NFC读写器读写IC卡
android·ide·android studio·引用·so·aar
不会写代码的猴子5 小时前
Android Studio AI助手---Gemini
android·ide·android studio
2401_854391085 小时前
SSM 架构下的垃圾分类系统,开启绿色生活
android·java·运维·安全
筒栗子8 小时前
复习打卡MySQL篇03
android·数据库·mysql
教我数理化_jwslh9 小时前
ImageView在setImageResource后发生了什么
android·性能优化
guoruijun_2012_410 小时前
在 ThinkPHP中 post 请求中 执行 异步 command ,该 command 创建一个命令行脚本 执行 curl请求 并设置其执行时间无限制
android
shankss11 小时前
网页跳转App,Universal Links(iOS)和 App Links(Android) 如何设置
android·flutter·ios
鲤籽鲲11 小时前
C# 异常处理 详解
android·java·c#
Billy_Zuo12 小时前
Android Room 数据库使用详解
android·数据库·room