Android ConstraintLayout 学习

各地山谷——你无法想象的美景

学习来源:鸿洋大神的公众号 拒绝拖拽 使用ConstraintLayout优化你的布局吧

1、作用

ConstraintLayout 允许您构建复杂的布局,而不必嵌套 View 和 ViewGroup 元素,使用 ConstraintLayout 布局能够减少 UI 的绘制,优化性能。

2、使用

image.png

要实现以上布局想必需要嵌套不少布局吧,现在告诉你使用一个ConstrainLayou就够了

  • Banner 页的布局
    这里只采用了一个 TextView 去做展示,实际中只需要用用相应的Banner库或者自己写的Banner界面去填充即可。布局如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#11ff0000"
    android:id="@+id/constraintLayout">

    <TextView
    android:id="@+id/banner"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="#765"
    android:gravity="center"
    android:text="Banner"
    app:layout_constraintDimensionRatio="H,16:9"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    />
    ....
    </android.support.constraint.ConstraintLayout>
  • 新的API

    1
    2
    3
    4
    5
    6
    7
     android:layout_width="0dp"                       // 需要设置为0dp,相当于match_parent
    android:layout_height="0dp" // 需要设置为0dp,相当于match_parent
    app:layout_constraintLeft_toLeftOf="parent" // 在父布局的左边
    app:layout_constraintRight_toRightOf="parent" // 在父布局的右边
    app:layout_constraintDimensionRatio="H,16:9" // 宽高比,需要填以上4个操作才有效果
    // app:layout_constraintDimensionRatio="W,16:6"
    // app:layout_constraintDimensionRatio="H,16:6"
  • 新闻item

    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
    <?xml version="1.0" encoding="utf-8"?>
    <android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#11ff0000"
    android:id="@+id/constraintLayout">

    .....

    <ImageView
    android:id="@+id/img_guitar"
    android:layout_width="140dp"
    android:layout_height="86dp"
    android:src="@drawable/guitar"
    android:layout_marginTop="12dp"
    android:layout_marginLeft="12dp"
    app:layout_constraintTop_toBottomOf="@+id/banner"
    app:layout_constraintLeft_toLeftOf="parent"
    />
    <TextView
    android:id="@+id/tv2"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_marginRight="12dp"
    android:text="马云:一年交税170多亿马云:一年交税170多亿马云:一年交税170多亿"
    android:textColor="#000000"
    android:textSize="16dp"
    app:layout_constraintLeft_toRightOf="@+id/img_guitar"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="@+id/img_guitar"
    />

    <TextView
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginLeft="8dp"
    android:layout_marginTop="12dp"
    android:text="8分钟前"
    android:textColor="#333"
    android:textSize="12dp"
    app:layout_constraintLeft_toRightOf="@+id/img_guitar"
    app:layout_constraintBottom_toBottomOf="@+id/img_guitar"
    />
    ......

    </android.support.constraint.ConstraintLayout>
  • 新的API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    图片在Banner的下方,图片在父布局的左边
    app:layout_constraintTop_toBottomOf="@+id/banner" // id是Top,要显示的是Bottom
    app:layout_constraintLeft_toLeftOf="parent"

    文字在banner下方,在图片左边满屏,顶部和图片对齐
    app:layout_constraintLeft_toRightOf="@+id/img_guitar" // img_guitar右边是文字
    app:layout_constraintRight_toRightOf="parent" // 需要设置
    layout_width="0dp",相当于match_parent
    app:layout_constraintTop_toTopOf="@+id/img_guitar" // 顶部对齐

    时间在图片的右边,与图片底部对齐
    app:layout_constraintLeft_toRightOf="@+id/img_guitar"
    app:layout_constraintBottom_toBottomOf="@+id/img_guitar"
  • 按钮

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    <Button
    android:id="@+id/btn1"
    android:layout_width="100dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="12dp"
    android:layout_marginLeft="12dp"
    android:text="你好"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/img_guitar"
    />
    <Button
    android:id="@+id/btn2"
    android:layout_width="0dp"
    android:layout_height="wrap_content"
    android:layout_marginTop="12dp"
    android:layout_marginLeft="12dp"
    android:text="你好"
    app:layout_constraintLeft_toRightOf="@+id/btn1"
    app:layout_constraintTop_toBottomOf="@+id/img_guitar"
    app:layout_constraintRight_toRightOf="parent"
    />
  • 按钮的实现没啥新的API,之前页使用过了,主要注意的就是需要修改 layout_width=”0dp” ,否则不能填满剩余的父布局

  • 底部的三个 Tab 实现

    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
    <TextView
    android:id="@+id/tab1"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#f67"
    android:gravity="center"
    android:text="Tab1"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintRight_toLeftOf="@+id/tab2"
    app:layout_constraintHorizontal_weight="1"
    />
    <TextView
    android:id="@+id/tab2"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#A67"
    android:gravity="center"
    android:text="Tab2"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@+id/tab1"
    app:layout_constraintRight_toLeftOf="@+id/tab3"
    app:layout_constraintHorizontal_weight="2"
    />
    <TextView
    android:id="@+id/tab3"
    android:layout_width="0dp"
    android:layout_height="30dp"
    android:background="#767"
    android:gravity="center"
    android:text="Tab3"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintLeft_toRightOf="@+id/tab2"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintHorizontal_weight="1"
    />
  • 主要思想就是两两互相约束
    app:layout_constraintHorizontal_weight="1"这个属性是设置占比,和LinearLayoutlayout_weight相像

  • 悬浮按钮的实现

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    <android.support.constraint.Guideline
    android:id="@+id/guideline_h"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:layout_constraintGuide_percent="0.8" // 横向距离顶部80%
    />
    <android.support.constraint.Guideline
    android:id="@+id/guideline_w"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="vertical"
    app:layout_constraintGuide_percent="0.8" // 纵向距离顶部80%
    />
    <android.support.design.widget.FloatingActionButton
    android:layout_width="60dp"
    android:layout_height="60dp"
    app:layout_constraintLeft_toRightOf="@id/guideline_w"
    app:layout_constraintTop_toBottomOf="@id/guideline_h" // 悬浮按钮就在二者的交点展示
    />
  • 新的API

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    android.support.constraint.Guideline该类比较简单,主要用于辅助布局,即类似为辅助线,横向的、纵向的。该布局是不会显示到界面上的。

    android:orientation取值为"vertical"和"horizontal".
    除此以外,还差个属性,决定该辅助线的位置:
    layout_constraintGuide_begin
    layout_constraintGuide_end
    layout_constraintGuide_percent

    可以通过上面3个属性其中之一来确定属性值位置。

    begin=30dp,即可认为距离顶部30dp的地方有个辅助线,根据orientation来决定是横向还是纵向。
    end=30dp,即为距离底部。 percent=0.8即为距离顶部80

在这里还可以通过这两个属性去实现这个悬浮按钮
layout_constraintHorizontal_bias=”0.9”
layout_constraintVertical_bias=”0.9”
即设置上下两侧间隙比例分别为90%与10%

1
2
3
4
5
6
7
8
9
10
<android.support.design.widget.FloatingActionButton
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintHorizontal_bias="0.9"
app:layout_constraintVertical_bias="0.9"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>

全部代码

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
133
134
135
136
137
138
139
140
141
142
143
144
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#11ff0000"
android:id="@+id/constraintLayout">

<TextView
android:id="@+id/banner"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="#765"
android:gravity="center"
android:text="Banner"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>

<ImageView
android:id="@+id/img_guitar"
android:layout_width="140dp"
android:layout_height="86dp"
android:src="@drawable/guitar"
android:layout_marginTop="12dp"
android:layout_marginLeft="12dp"
app:layout_constraintTop_toBottomOf="@+id/banner"
app:layout_constraintLeft_toLeftOf="parent"
/>
<TextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginRight="12dp"
android:text="马云:一年交税170多亿马云:一年交税170多亿马云:一年交税170多亿"
android:textColor="#000000"
android:textSize="16dp"
app:layout_constraintLeft_toRightOf="@+id/img_guitar"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@+id/img_guitar"
/>

<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="8dp"
android:layout_marginTop="12dp"
android:text="8分钟前"
android:textColor="#333"
android:textSize="12dp"
app:layout_constraintLeft_toRightOf="@+id/img_guitar"
app:layout_constraintBottom_toBottomOf="@+id/img_guitar"
/>
<Button
android:id="@+id/btn1"
android:layout_width="100dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginLeft="12dp"
android:text="你好"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@+id/img_guitar"
/>
<Button
android:id="@+id/btn2"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_marginTop="12dp"
android:layout_marginLeft="12dp"
android:text="你好"
app:layout_constraintLeft_toRightOf="@+id/btn1"
app:layout_constraintTop_toBottomOf="@+id/img_guitar"
app:layout_constraintRight_toRightOf="parent"
/>
<TextView
android:id="@+id/tab1"
android:layout_width="0dp"
android:layout_height="30dp"
android:background="#f67"
android:gravity="center"
android:text="Tab1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tab2"
app:layout_constraintHorizontal_weight="1"
/>
<TextView
android:id="@+id/tab2"
android:layout_width="0dp"
android:layout_height="30dp"
android:background="#A67"
android:gravity="center"
android:text="Tab2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/tab1"
app:layout_constraintRight_toLeftOf="@+id/tab3"
app:layout_constraintHorizontal_weight="2"
/>
<TextView
android:id="@+id/tab3"
android:layout_width="0dp"
android:layout_height="30dp"
android:background="#767"
android:gravity="center"
android:text="Tab3"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toRightOf="@+id/tab2"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_weight="1"
/>
<android.support.constraint.Guideline
android:id="@+id/guideline_h"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8"
/>
<android.support.constraint.Guideline
android:id="@+id/guideline_w"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8"
/>
<!--<android.support.design.widget.FloatingActionButton-->
<!--android:layout_width="60dp"-->
<!--android:layout_height="60dp"-->
<!--app:layout_constraintHorizontal_bias="0.9"-->
<!--app:layout_constraintVertical_bias="0.9"-->
<!--app:layout_constraintBottom_toBottomOf="parent"-->
<!--app:layout_constraintLeft_toLeftOf="parent"-->
<!--app:layout_constraintRight_toRightOf="parent"-->
<!--app:layout_constraintTop_toTopOf="parent"-->
<!--/>-->

<android.support.design.widget.FloatingActionButton
android:layout_width="60dp"
android:layout_height="60dp"
app:layout_constraintLeft_toRightOf="@id/guideline_w"
app:layout_constraintTop_toBottomOf="@id/guideline_h"/>
</android.support.constraint.ConstraintLayout>
小额支持我写出更好的文章~