引言 ConstraintLayout是Android Studio 2.2中主要的新增功能之一,也是Google在去年的I/O大会上重点宣传的一个功能。 ConstraintLayout最显著的优点就是它可以有效地解决布局嵌套过多 的问题。我们平时编写界面,复杂的布局总会伴随着多层的嵌套,而嵌套越多,程序的性能也就越差。ConstraintLayout则是使用约束的方式来指定各个控件的位置和关系的,它有点类似于RelativeLayout,但远比RelativeLayout要更强大。
添加依赖 我们需要在app/build.gradle文件中添加ConstraintLayout的依赖
Android Studio 3.0以下
compile ‘com.android.support.constraint:constraint-layout:1.0.2’
Android Studio3.0以上
implementation ‘com.android.support.constraint:constraint-layout:1.0.2’
Android Studio 3.0增加了许多新特性,依赖关键字的变化是其中之一,使用implementation
是新版本Android Studio默认的依赖关键字,它可以隐藏依赖的内部细节,加快编译速度。
示例 首先来看一个例子: 要实现上图所示的效果你一定在想这很简单啊,刷刷的就写出来了,然后发现嵌套了三四层,要是再放到列表里面你会发现页面滑动时很不流畅,这时就轮到ConstraintLayout出场了,先贴代码
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 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 <?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" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="@dimen/ui_180dp" android:background="@color/white" > <View android:id="@+id/view_mark" android:layout_width="@dimen/ui_5dp" android:layout_height="@dimen/one_and_a_half_grid_unit" android:layout_marginLeft="@dimen/ui_padding_10dp" android:background="@color/blue_line_chart" app:layout_constraintLeft_toRightOf="parent" app:layout_constraintTop_toTopOf="@+id/tv_title" app:layout_constraintBottom_toBottomOf="@id/tv_title" /> <TextView android:id="@+id/tv_title" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toRightOf="@id/view_mark" app:layout_constraintTop_toBottomOf="parent" android:layout_marginLeft="@dimen/ui_padding_10dp" android:layout_marginTop="@dimen/ui_padding_10dp" android:textSize="@dimen/ui_textsize_14sp" android:textColor="@color/black_title" tools:text="探鱼高新店" /> <TextView android:id="@+id/tv_leftItem" android:layout_width="0dp" android:layout_height="wrap_content" android:text="125,556,315" android:textColor="@color/black_title" android:paddingLeft="@dimen/ui_padding_10dp" android:gravity="center" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toLeftOf="@+id/guideline" /> <!--垂直平分线--> <android.support.constraint.Guideline android:id="@+id/guideline" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintRight_toLeftOf="@id/circlePoint1" app:layout_constraintGuide_percent="0.5" /> <!--垂直右边界线--> <android.support.constraint.Guideline android:id="@+id/guideline1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="1" /> <!--水平平分线--> <android.support.constraint.Guideline android:id="@+id/guideline2" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.5" /> <com.wangcaibao.erp.view.erpview.CirclePointView android:id="@+id/circlePoint1" android:layout_width="@dimen/ui_5dp" android:layout_height="@dimen/ui_5dp" app:fillColor="@color/gray" app:layout_constraintLeft_toRightOf="@+id/guideline" app:layout_constraintBottom_toBottomOf="@+id/tv_rightItem1" app:layout_constraintTop_toTopOf="@+id/tv_rightItem1" /> <com.wangcaibao.erp.view.erpview.CirclePointView android:id="@+id/circlePoint2" android:layout_width="@dimen/ui_5dp" android:layout_height="@dimen/ui_5dp" app:fillColor="@color/gray" app:layout_constraintBottom_toBottomOf="@+id/tv_rightItem2" app:layout_constraintLeft_toRightOf="@id/guideline" app:layout_constraintTop_toTopOf="@+id/tv_rightItem2" /> <com.wangcaibao.erp.view.erpview.CirclePointView android:id="@+id/circlePoint3" android:layout_width="@dimen/ui_5dp" android:layout_height="@dimen/ui_5dp" app:fillColor="@color/gray" app:layout_constraintBottom_toBottomOf="@+id/tv_rightItem3" app:layout_constraintLeft_toRightOf="@id/guideline" app:layout_constraintTop_toTopOf="@+id/tv_rightItem3" /> <com.wangcaibao.erp.view.erpview.CirclePointView android:id="@+id/circlePoint4" android:layout_width="@dimen/ui_5dp" android:layout_height="@dimen/ui_5dp" app:fillColor="@color/gray" app:layout_constraintBottom_toBottomOf="@+id/tv_rightItem4" app:layout_constraintLeft_toRightOf="@id/guideline" app:layout_constraintTop_toTopOf="@+id/tv_rightItem4" /> <TextView android:id="@+id/tv_rightItem1" android:layout_width="@dimen/ui_title_height" android:layout_height="@dimen/ui_title_height" android:gravity="center_vertical|right" android:textColor="@color/gray_text" android:textSize="@dimen/ui_textsize_12sp" android:text="点餐:" app:layout_constraintLeft_toRightOf="@id/circlePoint1" app:layout_constraintBottom_toTopOf="@id/tv_rightItem2" /> <TextView android:id="@+id/tv_number1" android:layout_width="@dimen/ui_title_width" android:layout_height="@dimen/ui_title_height" android:gravity="right|center_vertical" android:textColor="@color/black_title" android:textSize="@dimen/ui_textsize_14sp" tools:text="1234555" app:layout_constraintLeft_toRightOf="@id/tv_rightItem1" app:layout_constraintBottom_toTopOf="@id/tv_number2" /> <TextView android:id="@+id/tv_percent1" android:layout_width="@dimen/ui_55dp" android:layout_height="wrap_content" tools:background="@color/blue_line_chart" android:gravity="center_vertical" android:layout_marginLeft="@dimen/ui_padding_10dp" android:paddingLeft="@dimen/ui_5dp" android:textColor="@color/white" app:layout_constraintBottom_toTopOf="@+id/tv_number2" app:layout_constraintLeft_toRightOf="@id/tv_number1" app:layout_constraintTop_toTopOf="@+id/tv_number1" tools:text="80%" /> <TextView android:id="@+id/tv_rightItem2" android:layout_width="@dimen/ui_title_height" android:layout_height="@dimen/ui_title_height" android:gravity="center_vertical|right" android:textColor="@color/gray_text" android:textSize="@dimen/ui_textsize_12sp" app:layout_constraintBottom_toTopOf="@id/guideline2" app:layout_constraintLeft_toRightOf="@id/circlePoint2" android:text="游戏:" /> <TextView android:id="@+id/tv_number2" android:layout_width="@dimen/ui_title_width" android:layout_height="@dimen/ui_title_height" android:gravity="right|center_vertical" android:textColor="@color/black_title" android:textSize="@dimen/ui_textsize_14sp" app:layout_constraintLeft_toRightOf="@id/tv_rightItem1" app:layout_constraintBottom_toTopOf="@id/guideline2" tools:text="55" /> <TextView android:id="@+id/tv_percent2" android:layout_width="@dimen/ui_55dp" android:layout_height="wrap_content" tools:background="@color/blue_line_chart" android:gravity="center_vertical" android:layout_marginLeft="@dimen/ui_padding_10dp" android:paddingLeft="@dimen/ui_5dp" android:textColor="@color/white" app:layout_constraintBottom_toBottomOf="@+id/tv_number2" app:layout_constraintLeft_toRightOf="@id/tv_number2" app:layout_constraintTop_toTopOf="@+id/tv_number2" tools:text="80.66%" /> <TextView android:id="@+id/tv_rightItem3" android:layout_width="@dimen/ui_title_height" android:layout_height="@dimen/ui_title_height" android:gravity="center_vertical|right" android:textColor="@color/gray_text" android:textSize="@dimen/ui_textsize_12sp" app:layout_constraintLeft_toRightOf="@id/circlePoint2" app:layout_constraintTop_toBottomOf="@id/guideline2" android:text="支付:" /> <TextView android:id="@+id/tv_number3" android:layout_width="@dimen/ui_title_width" android:layout_height="@dimen/ui_title_height" android:gravity="right|center_vertical" android:textColor="@color/black_title" android:textSize="@dimen/ui_textsize_14sp" app:layout_constraintLeft_toRightOf="@id/tv_rightItem3" app:layout_constraintTop_toBottomOf="@id/guideline2" tools:text="55" /> <TextView android:id="@+id/tv_percent3" android:layout_width="@dimen/ui_55dp" android:layout_height="wrap_content" tools:background="@color/blue_line_chart" android:gravity="center_vertical" android:layout_marginLeft="@dimen/ui_padding_10dp" android:paddingLeft="@dimen/ui_5dp" android:textColor="@color/white" app:layout_constraintBottom_toBottomOf="@+id/tv_number3" app:layout_constraintLeft_toRightOf="@id/tv_number3" app:layout_constraintTop_toTopOf="@+id/tv_number3" tools:text="80%" /> <TextView android:id="@+id/tv_rightItem4" android:layout_width="@dimen/ui_title_height" android:layout_height="@dimen/ui_title_height" android:gravity="center_vertical|right" android:textColor="@color/gray_text" android:textSize="@dimen/ui_textsize_12sp" app:layout_constraintLeft_toRightOf="@id/circlePoint2" app:layout_constraintTop_toBottomOf="@id/tv_rightItem3" android:text="服务:" /> <TextView android:id="@+id/tv_number4" android:layout_width="@dimen/ui_title_width" android:layout_height="@dimen/ui_title_height" android:gravity="right|center_vertical" android:textColor="@color/black_title" android:textSize="@dimen/ui_textsize_14sp" app:layout_constraintLeft_toRightOf="@id/tv_rightItem3" app:layout_constraintTop_toBottomOf="@id/tv_number3" tools:text="55" /> <TextView android:id="@+id/tv_percent4" android:layout_width="@dimen/ui_55dp" android:layout_height="wrap_content" tools:background="@color/blue_line_chart" android:gravity="center_vertical" android:textColor="@color/white" android:layout_marginLeft="@dimen/ui_padding_10dp" android:paddingLeft="@dimen/ui_5dp" app:layout_constraintBottom_toBottomOf="@+id/tv_number4" app:layout_constraintLeft_toRightOf="@id/tv_number4" app:layout_constraintTop_toTopOf="@+id/tv_number4" tools:text="80%" /> <ImageView android:id="@+id/iv_next" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentRight="true" android:layout_centerVertical="true" android:contentDescription="@string/view_details" android:src="@drawable/icon_drop_right" app:layout_constraintRight_toLeftOf="@id/guideline1" app:layout_constraintTop_toBottomOf="parent" app:layout_constraintBottom_toTopOf="parent" /> <View android:layout_width="match_parent" android:layout_height="@dimen/ui_divider_height" android:background="@color/divider" app:layout_constraintBottom_toTopOf="parent" /> </android.support.constraint.ConstraintLayout>
可以看到使用ConstraintLayout只用一层布局就可以做到,完全不用嵌套,而且性能比普通的嵌套布局好很多,可以用Hierarchy View查看布局时间,图这里就不贴了。
使用 ConstraintLayout有两种布局方式,一种就是在视图编辑器里直接拖动,另外一种就是在代码里布局,我的建议是简单的布局可以在视图编辑器里直接拖,很方便,但是复杂布局还是建议大家在代码里布局,因为view太多了真的不好拖,还容易误操作,当然你有一个巨大无比的显示屏就当我没说。
1.在视图编辑器里直接拖动
这里引用一下郭霖郭神的blog,他的博客已经写的很清楚了。想了解的可以点击郭霖的博客
2.在代码里布局
相对于直接在视图编辑器里布局,在代码里布局就不是那么直观明了了,但是用代码布局更加准确,不容易出错。
基本布局代码:
app:layout_constraintLeft_toRightOf=”parent”
上面代码layout_constraintLeft
表示要布局的view自身的四个位置中的左边,toRightOf="parent"
表示相对于目标view的位置右边,这行代码连起来就是要布局的view的左边在parent view的右边,也就是view在parent view的右边的意思
app:layout_constraintBottom_toBottomOf=”parent”
对于这种类似于bottom_toBottom的代码,是表示边与边对齐的意思,这行代码的意思是view的底边相对于parent view底边对齐
1 2 3 app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent"
上面代码是表示垂直居中的意思
引导线(可用来百分比布局) 1 2 3 4 5 6 7 8 <!--水平平分线--> <android.support.constraint.Guideline android:id="@+id/guideline" android:layout_width="match_parent" android:layout_height="wrap_content" android:orientation="horizontal" app:layout_constraintGuide_percent="0.5" > </android.support.constraint.Guideline>
GuideLine也叫做辅助线,分为垂直和水平方向,查看源码可以看到它的draw()方法是空实现,也就表示在它不会真正绘制,只是起辅助作用,通过辅助线可以简单实现百分比布局等功能。通过GuideLine和app:layout_constraintXX_toXXOf=”XX”配合使用,基本可以实现所有复杂布局。
总结 ConstraintLayout作为新的布局容器,优点是能良好的解决布局嵌套带来的性能问题,在追求性能的页面很有必要使用,缺点就是便利性不够,简而言之就是稍显麻烦,一般对性能要求不高的页面不是很必要,这个希望能继续优化吧,大家在日常工作中根据实际情况来使用就行了。