Android移动开发基础案例教程
上QQ阅读APP看书,第一时间看更新

2.2 布局的类型

为了适应不同的界面风格,Android 系统为开发人员提供了5种常用布局,分别是 Linear Layout(线性布局)、RelativeLayout(相对布局)、FrameLayout(帧布局)、TableLayout(表格布局)、AbsoluteLayout(绝对布局),本节将针对这5种布局进行讲解。

2.2.1 线性布局

线性布局(LinearLayout)在实际开发中比较常用,它主要以水平和垂直方式来显示界面中的控件。当控件水平排列时,显示顺序依次为从左到右;当控件垂直排列时,显示顺序依次为从上到下。

在线性布局中,有一个非常重要的属性 orientation,用于控制控件的排列方向,该属性有vertical和horizontal(默认)两个值,其中,vertical表示线性布局垂直显示,horizontal表示线性布局水平显示。接下来通过orientation属性,设置3个按钮垂直排列,具体代码如文件2-1所示。

文件2-1 linearlayout1.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:orientation="vertical">

  <Button

   android:id="@+id/btn_one"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:text="按钮1"/>

  <Button

   android:id="@+id/btn_two"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:text="按钮2"/>

  <Button

   android:id="@+id/btn_three"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:text="按钮3"/>

</LinearLayout>

在上述代码中,将 orientation 属性值设置为 vertical,控件垂直显示。若将该值修改为horizontal,则控件会水平显示,预览效果如图2-3所示。

图2-3 控件垂直排列和水平排列

需要注意的是,当控件水平排列时,控件属性 layout_width 只能设置为 wrap_content(包裹内容让当前控件根据控件内容大小自动伸缩),不能设置为match_parent(填充父窗体由父容器大小决定控件大小),否则其余控件会被挤出屏幕右侧不显示。同理,如果控件垂直排列也会出现同样情况。

从图2-3可以看出,当控件水平排列时,3个Button未占满一行,右侧留有空白区域,这样既不美观又浪费空间。此时,利用layout_weight属性可完美解决这个问题,该属性被称为权重,通过比例调整布局中所有控件的大小,在进行屏幕适配时起到关键作用,具体代码如文件2-2所示。

文件2-2 linearlayout2.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="wrap_content">

  <Button

   android:id="@+id/btn_one"

   android:layout_width="0dp"

   android:layout_height="wrap_content"

   android:layout_weight="1"

   android:text="按钮1"/>

  <Button

   android:id="@+id/btn_two"

   android:layout_width="0dp"

   android:layout_height="wrap_content"

   android:layout_weight="1"

   android:text="按钮2"/>

  <Button

   android:id="@+id/btn_three"

   android:layout_width="0dp"

   android:layout_height="wrap_content"

   android:layout_weight="2"

   android:text="按钮3"/>

</LinearLayout>

在上述代码中,需将父控件的 layout_width 的属性值设置为“match_parent”,Button 中 layout_weight 的属性值可直接填写数字,1表示在整个控件中占据权重值为1。原理是Android先会把布局内所有控件 layout_weight 属性值相加得到总值,然后用该控件layout_weight属性值除以总值,得到每个控件的占比,根据占比分配控件所占大小。以上述代码为例,“按钮1”和“按钮2”权重值是1,“按钮3”权重值是2。“按钮1”的计算方式是,因此占据1/4的位置。预览效果如图2-4所示。

需要注意的是,在上述代码中线性布局 layout_width 的属性值不可设为wrap_content,因为LinearLayout的优先级比Button高,所以Button标签中layout_weight属性会失去作用。当Button标签中使用layout_weight时,控件宽度不再由layout_width来决定,所以指定为0dp不会影响效果,这样写也是一种规范。

图2-4 layout_weight属性效果

2.2.2 相对布局

在Android程序创建时,默认采用的就是相对布局(RelativeLayout)。相对布局是通过相对定位的方式指定控件位置,即以其他控件或父容器为参照物,摆放控件位置。在设计相对布局时要遵循控件之间的依赖关系,后放入控件的位置依赖于先放入的控件。

相对布局属性较多,但都是有规律的,所以不难理解,下面先来介绍在布局内控件摆放位置的属性,如表2-1所示。

表2-1 设置控件位置的属性

再来看一下相对于某控件间距的属性,如表2-2所示。

表2-2 设置控件间距的属性

最后介绍在布局中设置内边距的属性,如表2-3所示。

表2-3 设置布局内边距的属性

下面通过上述属性设置3个按钮的位置,通过效果图对比更好地理解其作用,具体代码如文件2-3所示。

文件2-3 relativelayout.xml

<?xml version="1.0" encoding="utf-8"?>

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:paddingBottom="20dp">

  <Button

   android:id="@+id/btn_one"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:layout_alignParentBottom="true"

   android:text="按钮1"/>

  <Button

   android:id="@+id/btn_two"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:layout_centerHorizontal="true"

   android:layout_marginTop="260dp"

   android:text="按钮2"/>

  <Button

   android:id="@+id/btn_three"

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:layout_alignBottom="@id/btn_two"

   android:layout_marginBottom="100dp"

   android:layout_toRightOf="@id/btn_two"

   android:text="按钮3"/>

</RelativeLayout>

在上述代码中,使用 RelativeLayout 标签定义了一个相对布局,并在该布局中添加3个按钮,通过设置属性控制每个控件位置,预览效果如图2-5所示。

图2-5 RelativeLayout布局

通过观察图2-5与上述代码可知,在RelativeLayout布局标签中通过paddingBottom属性指定布局与屏幕底部边距为20dp。

“按钮1”通过layout_alignParentBottom属性指定当前控件位于布局底端,通过这两个属性的控制,“按钮1”的位置距屏幕底部20dp。

“按钮2”通过layout_centerHorizontal属性指定它在父布局中水平居中,通过layout_marginTop属性指定当前控件上边缘与父布局顶部距离260dp。

“按钮3”通过layout_alignBottom属性指定它与“按钮2”底部对齐,通过layout_marginBottom属性指定距离“按钮2”底部100dp,通过layout_toRightOf属性指定当前按钮在“按钮2”右边。

多学一招:控件的单位

为了让程序拥有更好的屏幕适配能力,在指定控件和布局宽高时最好使用“match_parent”或“wrap_content”,尽量避免将控件宽高设置固定值。因为在控件很多的情况下会相互挤压,使控件变形。但特殊情况下需要使用指定宽高值时,可以选择使用px、pt、dp、sp四种单位。例如,android:layout_width="20dp"代表指定值是20dp。

• px:代表像素,即在屏幕中可以显示的最小元素单位,应用程序中任何控件都是由一个个像素点组成的。分辨率越高的手机,屏幕的像素点就越多。因此,如果使用 px 控制控件的大小,在分辨率不同的手机上控件显示的大小也会不同。

• pt:代表磅数,一磅等于1/72英寸,一般pt都会作为字体的单位来显示。pt和px的情况类似,在不同分辨率的手机上,用pt控件的字体大小也会不同。

• dp:一种基于屏幕密度的抽象单位。不同设备有不同的显示效果,它是根据设备分辨率的不同来确定控件的尺寸。

• sp:代表可伸缩像素,采用与dp相同的设计理念,推荐设置文字大小时使用。

2.2.3 帧布局

帧布局(FrameLayout)是Android中最为简单的一种布局,该布局为每个加入其中的控件创建一个空白区域(称为一帧,每个控件占据一帧)。采用帧布局方式设计界面时,所有控件都默认显示在屏幕左上角,并按照先后放入的顺序重叠摆放,先放入的控件显示在最底层,后放入的控件显示在最顶层。帧布局适用于图层设计,例如应用图标上信息提示数量。帧布局的大小由内部最大控件决定,它有两个特殊属性,具体如表2-4所示。

表2-4 FrameLayout属性

接下来通过两个按钮来展示帧布局效果,具体代码如文件2-4所示。

文件2-4 framelayout.xml

<?xml version="1.0" encoding="utf-8"?>

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent"

  android:foreground="@mipmap/ic_launcher"

  android:foregroundGravity="left" >

  <Button

   android:layout_width="300dp"

   android:layout_height="450dp"

   android:text="按钮1" />

  <Button

   android:layout_width="200dp"

   android:layout_height="210dp"

   android:text="按钮2" />

</FrameLayout>

在上述代码中,添加两个按钮和一张前景图片,预览效果如图2-6所示。

从图2-6可以看出,最先放入的“按钮1”位于最底层,后放入的按钮依次覆盖。前景图片是通过FrameLayout标签中的foreground属性设置的,并使用foregroundGravity属性设置图片居左。需要注意的是,前景图片始终保持在最上层。

图2-6 FrameLayout布局

2.2.4 表格布局

表格布局(TableLayout)是以表格形式排列控件的,通过行和列将界面划分为多个单元格,每个单元格都可以添加控件。表格布局需要和 TableRow 配合使用,每一行都由 TableRow 对象组成,因此TableRow的数量决定表格的行数。而表格的列数是由包含最多控件的TableRow 决定的,例如第1个 TableRow 有两个控件,第2个TableRow有3个控件,则表格列数为3。

TableLayout 继承自 LinearLayout 类,除了继承了父类的属性和方法,还包含了一些表格布局的特有属性,其属性如表2-5所示。

表2-5 TableLayout布局属性

表格布局中控件有两个常用属性,分别用于设置控件显示位置、占据行数,如表2-6所示。

表2-6 TableLayout控件属性

接下来编写一个表格布局,并使用上述属性,具体代码如文件2-5所示。

文件2-5 tablelayout.xml

<?xml version="1.0" encoding="utf-8"?>

<TableLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="wrap_content"

  android:layout_height="wrap_content"

  android:stretchColumns="2">

  <TableRow>

   <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_column="0"

    android:text="按钮1" />

   <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_column="1"

    android:text="按钮2" />

  </TableRow>

  <TableRow>

   <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_column="1"

    android:text="按钮3"/>

   <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_column="2"

    android:text="按钮4"/>

  </TableRow>

  <TableRow>

   <Button

    android:layout_width="wrap_content"

    android:layout_height="wrap_content"

    android:layout_column="2"

    android:text="按钮5"/>

  </TableRow>

</TableLayout>

在上述代码中,设置了一个3行3列的表格布局,并通过stretch Columns属性指定表格布局的第3列被拉伸(下标值从0开始计算),通过layout_column属性指定当前控件位于第几列,预览效果如图2-7所示。

图2-7 TableLayout布局

需要注意的是,在TableRow标签中设置layout_width和layout_height属性是没有作用的,其宽度layout_width和高度layout_height会自动根据单元格控件决定,所以通常会省略这两个属性。如果其他控件在TableRow标签外,会自成一行。

2.2.5 绝对布局

绝对布局(AbsoluteLayout)是通过指定xy坐标来控制每一个控件位置的。随着智能手机种类增多,屏幕分辨率千变万化,使用绝对布局需要精确地计算控件大小,同时还要考虑手机屏幕尺寸和分辨率,在开发中这是非常低效的,因此不推荐使用。同时,在GoogleAPI中提示此类已弃用,可使用 FrameLayout、RelativeLayout 代替它,大家只需了解即可。下面介绍一下设置控件位置的两个属性,具体如表2-7所示。

表2-7 AbsoluteLayout属性

接下来通过一段代码来演示如何使用绝对布局,具体代码如文件2-6所示。

文件2-6 absolutelayout.xml

<?xml version="1.0" encoding="utf-8"?>

<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android"

  android:layout_width="match_parent"

  android:layout_height="match_parent">

  <Button

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:layout_x="50dp"

   android:layout_y="50dp"

   android:text="按钮1"/>

  <Button

   android:layout_width="wrap_content"

   android:layout_height="wrap_content"

   android:layout_x="200dp"

   android:layout_y="150dp"

   android:text="按钮2"/>

</AbsoluteLayout>

在上述代码中,通过layout_x和layout_y属性控制2个按钮的位置,预览效果如图2-8所示。

图2-8 AbsoluteLayout布局

从图2-8可以看出,两个按钮以左上角为坐标原点,根据指定xy值准确地定位在屏幕中。“按钮1”的layout_x属性指定在x坐标的第50dp像素上,layout_y属性表示控件在y坐标的第50dp像素上,“按钮2”同样通过xy值设置控件位置。