Android 五大布局

布局分为:FrameLayout(帧布局,框架布局),Linearlayout(线性布局),AbsoluteLayout(绝对布局),RelativeLayout(相对布局),TableLayout(表格布局)。

它们的绘制效率对比,相同层级来讲,FramenLayout效率最高,以下依次是LinearLayout,RelativeLayout,TableLayout。而AbsoluteLayout已经不用了,就不管了。

对于绘制效率,重点区分Linearlayout和Relativelayout。它们的layout和draw的过程时间消耗相差无几,关键在于measure过程RelativeLayout比LinearLayout慢了一些,因为它需要横向纵向分别进行一次排序测量。而Linearlayout则根据orientation属性进行一次绘制就可以了。但是,如果LinearLayout使用了weight属性,也会导致两次的measure绘制。

FrameLayout

最简单的布局,它并没有对Child View的摆布进行控制,所有的子元素(控件或布局)都会默认在试图的左上角,后面的元素会覆盖前面的元素,可通过android:layout_margin,android:layout_gravity等属性去控制子元素相对布局的位置。

Linearlayout

子元素(控件或布局)会按照水平或竖直的方向依次按顺序排列。可通过android:orientation=“horizontal|vertical属性来控制排列的方向。
注:

  • android:orientation="horizontal"时,其子元素的android:layout_gravity="right|left" 等控制水平方向的gravity值都是被忽略的,此时子元素都是默认的按照水平从左向右来排列,我们可以用android:layout_gravity="top|bottom"等gravity值来控制垂直展示。反之亦然。
  • android:layout_weight属性:表示权重,子元素占据的空间大小比例。数值越大,占据的空间越大。常用来实现等比例分配控件或布局。

示例:等比例分配布局

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<TextView
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="1"/>
<TextView
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="2"/>
<TextView
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="3"/>
</LinearLayout>

示例:也可用来实现,占满剩余的空间。因为线性布局的特性,如果是水平方向的排列,则此控件相对于父布局的控制左右位置的属性是无效的,所以如果想让一个控件位于最右侧,可以让前一个控件占满剩余空间。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<!--左部按钮-->
<Button
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="left"/>
<TextView
android:gravity="center"
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:text="center"/>
<!--右侧按钮-->
<Button
android:gravity="center"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:text="right"/>
</LinearLayout>
<!--分割线-->
<View
android:layout_width="match_parent"
android:layout_height="1dp"
android:background="#e5e5e5" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="40dp"
android:orientation="horizontal">
<!--Space控件是在Android 4.0中加入,是个空白的view。-->
<!--Space控件在布局中只占位置,而不去绘制渲染。-->
<!--组件中的间隙用Space控件填充比用其它控件填充可以提高绘制效率。-->
<Space
android:layout_width="50dp"
android:layout_height="match_parent"
/>
<TextView
android:layout_width="0dp"
android:layout_weight="1"
android:layout_height="match_parent"
android:gravity="center"
android:background="@color/red"/>
<Space
android:layout_width="50dp"
android:layout_height="match_parent"
/>
</LinearLayout>

图例:

AbsoluteLayout

可以放置多个控件,并且可以自己定义控件的x,y位置。但已经不用了。

RelativeLayout

Android对该布局的child view的水平layout和垂直layout做了解析。它会按照子元素的相对位置关系完成布局。也是Google推荐的布局,相较于Linearlayout,它更为灵活,非常适合一些比较复杂的界面设计。对于绘制效率来讲,Linearlayout只需绘制一次(但是,如果使用了weight属性,也会导致两次measure),而RelativeLayout则需要对横向和竖向进行两次绘制。
注:在对控件定位时,需要已知相对控件的id。
相关属性:

属性 含义 示例
layout_toLeftOf 位于引用组件的左方 android:layout_toLeftOf="@id/tv_center"
layout_toRightOf 位于引用组件的右方 android:layout_toRightOf="@id/tv_center"
layout_above 位于引用组件的上方 android:layout_above="@id/tv_center"
layout_below 位于引用组件的下方 android:layout_below="@id/tv_center"
layout_alignParentLeft 是否对齐父组件的左端 android:layout_alignParentLeft="true"
layout_alignParentRight 是否对齐父组件的右端 android:layout_alignParentRight="true"
layout_alignParentTop 是否对齐父组件的顶部 android:layout_alignParentTop="true"
layout_alignParentBottom 是否对齐父组件的底部 android:layout_alignParentBottom="true"
layout_centerInParent 是否相对于父组件居中 android:layout_centerInParent="true"
layout_centerHorizontal 是否横向居中 android:layout_centerHorizontal="true"
layout_centerVertical 是否垂直居中 android:layout_centerVertical="true"
layout_alignLeft 左侧相对于给定ID组件的左侧 android:layout_alignLeft="@id/tv_center"
layout_alignRight 右侧相对于给定ID组件的右侧 android:layout_alignRight="@id/tv_center"
layout_alignTop 顶部相对于给定ID组件的顶部 android:layout_alignTop="@id/tv_center"
layout_alignBottom 底部相对于给定ID组件的底部 android:layout_alignBottom="@id/tv_center"

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<!--相对控件-->
<TextView
android:background="@color/red"
android:id="@+id/tv_center"
android:layout_margin="20dp"
android:layout_centerInParent="true"
android:layout_width="200dp"
android:layout_height="100dp"
/>
<!--位于center的左侧-->
<TextView
android:layout_centerInParent="true"
android:layout_toLeftOf="@id/tv_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="toLeftOf"/>
<!--位于center的右侧-->
<TextView
android:layout_centerInParent="true"
android:layout_toRightOf="@id/tv_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="toRightOf"/>
<!--位于center的上方-->
<TextView
android:layout_centerInParent="true"
android:layout_above="@id/tv_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="above"/>
<!--位于center的下方-->
<TextView
android:layout_centerInParent="true"
android:layout_below="@id/tv_center"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="below"/>
<!--左侧相对于center的左侧对齐,并相对于父布局垂直居中-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alignLeft"
android:textColor="@color/white"
android:layout_centerVertical="true"
android:layout_alignLeft="@id/tv_center"/>
<!--右侧相对于center的右侧对齐,并相对于父布局垂直居中-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alignRight"
android:textColor="@color/white"
android:layout_centerVertical="true"
android:layout_alignRight="@id/tv_center"/>
<!--顶部相对于center的顶部对齐,并相对于父布局水平居中-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alignTop"
android:textColor="@color/white"
android:layout_centerHorizontal="true"
android:layout_alignTop="@id/tv_center"/>
<!--底部相对于center的底部对齐,并相对于父布局水平居中-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="alignBottom"
android:textColor="@color/white"
android:layout_centerHorizontal="true"
android:layout_alignBottom="@id/tv_center"/>
<!--位于center内部的左上方-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tv_center"
android:layout_alignTop="@id/tv_center"
android:text="内左上"
android:gravity="center"
android:textColor="@color/white"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@id/tv_center"
android:layout_alignTop="@id/tv_center"
android:text="内右上"
android:gravity="center"
android:textColor="@color/white"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignLeft="@id/tv_center"
android:layout_alignBottom="@id/tv_center"
android:text="内左下"
android:gravity="center"
android:textColor="@color/white"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_alignRight="@id/tv_center"
android:layout_alignBottom="@id/tv_center"
android:text="内右下"
android:gravity="center"
android:textColor="@color/white"/>
<!--位于center外部的左上方-->
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/tv_center"
android:layout_toLeftOf="@id/tv_center"
android:text="外左上"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/tv_center"
android:layout_toRightOf="@id/tv_center"
android:text="外右上"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_center"
android:layout_toLeftOf="@id/tv_center"
android:text="外左下"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_below="@+id/tv_center"
android:layout_toRightOf="@id/tv_center"
android:text="外右下"/>
</RelativeLayout>

图例:

示例:RelativeLayout的等比例分配空间。复杂的还是推荐使用Linearlayout来实现。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<RelativeLayout
android:layout_width="match_parent"
android:layout_height="40dp">
<View
android:layout_toLeftOf="@id/line"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@color/red"/>
<!--参照物,以它分割-->
<Space
android:id="@+id/line"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
<View
android:layout_toRightOf="@id/line"
android:layout_width="match_parent"
android:layout_height="match_parent"
/>
</RelativeLayout>

TableLayout

表格布局,适用于多行多列的布局格式。它将子元素的位置分配到行或列中,一个TableLayout由许多的TableRow组成。
一个TableRow就表示TableLayout中的每一行,这一行可以由多个子元素组成。
实际上TableLayout和TableRow都是LineLayout线性布局的子类。但是TableRow的参数android:orientation属性值固定为horizontal,且android:layout_width=MATCH_PARENT,android:layout_height=WRAP_CONTENT。所以TableRow实际是一个横向的线性布局,且所以子元素宽度和高度一致。
注意:在TableLayout中,单元格可以为空,但是不能跨列,意思是只能不能有相邻的单元格为空。
在TableLayout布局中,一列的宽度由该列中最宽的那个单元格指定,而该表格的宽度由父容器指定。可以为每一列设置以下属性:

  • Shrinkable  表示该列的宽度可以进行收缩,以使表格能够适应父容器的大小
    android:shrinkColumns=”0,1,2” // 设置三列都可以收缩
  • Stretchable 表示该列的宽度可以进行拉伸,以使能够填满表格中的空闲空间
    android:stretchColumns = “0,1,2,3”// 设置三列都可以拉伸 如果不设置这个,那个显示的表格将不能填慢整个屏幕
  • Collapsed  表示该列会被隐藏
    android:collapseColumns

示例:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
<TableLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical"
android:shrinkColumns="0,1,2"
android:stretchColumns="0,1,2">

<TableRow android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button android:gravity="center"
android:padding="10dp"
android:text="Button1">
</Button>

<Button android:gravity="center"
android:padding="10dp"
android:text="Button2">
</Button>

<Button android:gravity="center"
android:padding="10dp"
android:text="Button3">
</Button>

</TableRow>

<TableRow android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button android:gravity="center"
android:padding="10dp"
android:text="Button4">
</Button>

<Button android:gravity="center"
android:padding="10dp"
android:text="Button5">
</Button>

</TableRow>

<TableRow android:layout_width="match_parent"
android:layout_height="wrap_content">

<Button android:gravity="center"
android:padding="10dp"
android:text="Button6">
</Button>

<Button android:gravity="center"
android:padding="10dp"
android:text="Button7">
</Button>

<Button android:gravity="center"
android:padding="10dp"
android:text="Button8">
</Button>
</TableRow>
</TableLayout>

常用属性

属性 含义 示例
id 控件id android:id="@+id/id"
layout_margin 外边距 android:layout_margin="20dp"
padding 内边距 android:padding="20dp"
layout_gravity 本身相对于父布局位置 android:layout_gravity="center"
gravity 子元素相对于本身的位置 android:gravity="center"
background 设置背景,图片或者颜色 android:background="@color/red"
android:background="@mipmap/ic_launcher"
android:background="#00ff00"
visibility 是否显示布局 android:visibility="invisible"