1、概述
ConstraintLayout 布局已经出来有一两年了,最早开始由于视图化的布局,因此一直没有使用过,最近浏览其余博客的时候,屡次看到ConstraintLayout 是官方推荐使用的布局,并且相对于其余的四大布局,有不少性能方面的优点。因此有必要学习和使用一下这个布局。下面开始吧!
引入依赖(已经到1.1版本了,是应该多尝试使用这个布局了)android
implementation 'com.android.support.constraint:constraint-layout:1.1.0'
2、效果展现
不喜欢视图化布局,其实也能够手写属性来布局。下面展现下我看hongyang大神博客时手写布局的效果。
下面是布局xml代码:markdown
<?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="match_parent"> <ImageView android:id="@+id/img_banner" android:layout_width="0dp" android:layout_height="0dp" android:layout_marginLeft="10dp" android:layout_marginRight="10dp" android:layout_marginTop="15dp" android:background="@color/colorPrimaryDark" app:layout_constraintDimensionRatio="H,16:9" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" /> <ImageView android:id="@+id/img_left" android:layout_width="146dp" android:layout_height="86dp" android:layout_marginBottom="10dp" android:layout_marginLeft="12dp" android:layout_marginTop="10dp" android:background="@color/colorPrimary" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toBottomOf="@+id/img_banner" /> <TextView android:id="@+id/txt_content" android:layout_width="0dp" android:layout_height="wrap_content" android:layout_marginLeft="10dp" android:text="马云:一年交税170多亿马云:一年交税170多亿马云:一年交税170多亿" app:layout_constraintLeft_toRightOf="@+id/img_left" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="@+id/img_left" /> <TextView android:layout_width="0dp" android:layout_height="wrap_content" android:text="8分钟前" app:layout_constraintBottom_toBottomOf="@+id/img_left" app:layout_constraintLeft_toLeftOf="@+id/txt_content" /> <TextView android:layout_width="60dp" android:layout_height="60dp" android:background="@color/colorPrimary" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintHorizontal_bias="0.9" app:layout_constraintVertical_bias="0.9"/> <TextView android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tab2" /> <TextView android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_green_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toRightOf="@+id/tab1" app:layout_constraintRight_toLeftOf="@+id/tab3" /> <TextView android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_red_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintHorizontal_chainStyle="spread" app:layout_constraintLeft_toRightOf="@+id/tab2" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>
3、属性介绍
结合这个上面这个布局介绍下ConstraintLayout的属性吧app
一、相对位置(Relative positioning)
在横向和纵向上添加约束关系来固定控件位置,官方一共提供给咱们这些相对约束属性:
下面咱们对比下效果
没有添加约束布局
<?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:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮01"/> <Button android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2"/> </android.support.constraint.ConstraintLayout>
没有添加按钮2在按钮1的右边的约束性能
<?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:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮01"/> <Button android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintLeft_toRightOf="@+id/btn_01"/> </android.support.constraint.ConstraintLayout>
仅仅添加了一个app:layout_constraintLeft_toRightOf="@+id/btn_01"
属性就能够达到了RelativeLayout布局的android:layout_toLeftOf="@id/btn_1"
所要的效果。
相对位置的约束属性的格式基本是layout_constraintxxx_toxxxOf=id这种格式,理解起来其实并不难,constraintxxx
表明当前控件的约束方向,如上图的效果constraintLeft就是就是btn_02按钮的左边约束。toxxxOf
被约束的控件的方向,如上图id是btn_01 就表明与id为btn_01控件的右边方向约束在一块儿。app:layout_constraintLeft_toRightOf="@+id/btn_01"
结合起来就是当前控件btn_01按钮的左边与id为btn_01的控件的右边相约束。 关于约束这个词的理解,你能够理解成用带弹性的绳子相链接起来。
下面在展现几个例子:
学习
<?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:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="按钮01"/> <Button android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintLeft_toLeftOf="@+id/btn_01" app:layout_constraintTop_toBottomOf="@+id/btn_01" app:layout_constraintRight_toRightOf="@+id/btn_01"/> </android.support.constraint.ConstraintLayout>
首先对按钮01 使用app:layout_constraintLeft_toLeftOf="parent"
和app:layout_constraintTop_toTopOf="parent"
使得按钮01的左边和顶部与父布局的左边和顶部约束,这样按钮就被固定在左上角。 而后对按钮02 使用app:layout_constraintLeft_toLeftOf="@+id/btn_01"
将按钮02的左边与按钮01的左边相约束,而后使用app:layout_constraintTop_toBottomOf="@+id/btn_01"
让按钮02的顶部与按钮01的底部相约束,这样按钮02就在按钮01的正下方。最后使用 app:layout_constraintRight_toRightOf="@+id/btn_01"
让按钮02的右边与按钮01的右边相约束,保持永远对齐。google
二、倾向(bias)
倾向分为两个方向 横向和纵向, 也就是说左右和上下两边出现受力不均,形成倾向,好比左边约束的力是右边约束的力之比是9:1atom
<?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:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="180dp" android:layout_height="wrap_content" android:layout_marginLeft="80dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" android:text="按钮01"/> <Button android:id="@+id/btn_02" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintVertical_bias="0.3" app:layout_constraintHorizontal_bias="0.9"/> </android.support.constraint.ConstraintLayout>
理解:左边的间距占左右边间距之和的90%,上间距占上下间距之和的30%spa
三、圆心定位
这是在1.1版本添加的新属性,貌似没有自动提示
.net
<?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:layout_width="match_parent" android:layout_height="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="80dp" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintBottom_toBottomOf="parent" android:text="按钮01"/> <Button android:id="@+id/btn_02" android:layout_width="80dp" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintCircle="@+id/btn_01" app:layout_constraintCircleRadius="90dp" app:layout_constraintCircleAngle="20"/> </android.support.constraint.ConstraintLayout>
圆心定位意思就是基于两个控件的中心,经过radius和angle来控制控件的位置。angle角度不支持负值。默认以被定位控件(btn_01)的Y轴正方向为零度。
四、可见性约束
能够看到区别开始是按钮01左边约束父布局的左边,而后按钮02约束按钮01的右边。 可是当按钮01隐藏之后,按钮02直接约束到父布局的左边,事实上按钮根本没有约束父布局的左边。 这里小编的理解,就是以前的隐藏的控件的布局约束依然有效,只不过按钮01的全部边距变成了0.若是你有更好的理解请告诉我,谢谢。
五、控件尺寸约束
一般咱们定义控件的长和宽,android:layout_width=""
和android:layout_height=""
来设置控件的大小。
ConstraintLayout布局设置方式:
- 固定值
- wrap_content
- 0dp(至关于MATCH_CONSTRAINT)
那match_parent呢?看下面这段话
Important: MATCH_PARENT is not recommended for widgets contained in a ConstraintLayout. Similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to “parent”.
大概意思是不推荐使用match_parent在ConstraintLayout布局中设置大小,相似的功能可使用约束设置左右或者上下指定约束到父布局上。
那怎样实现其余四大布局match_parent沾满父窗体剩下控件的效果呢? 可使用0dp来代替
match_parent的效果
<?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="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="48dp" android:layout_marginTop="112dp" android:text="按钮01" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/> <Button android:id="@+id/btn_02" android:layout_width="match_parent" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintLeft_toRightOf="@+id/btn_01" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>
0dp实现的效果
<?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="match_parent"> <Button android:id="@+id/btn_01" android:layout_width="80dp" android:layout_height="wrap_content" android:layout_marginLeft="48dp" android:layout_marginTop="112dp" android:text="按钮01" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintTop_toTopOf="parent"/> <Button android:id="@+id/btn_02" android:layout_width="0dp" android:layout_height="wrap_content" android:text="按钮2" app:layout_constraintLeft_toRightOf="@+id/btn_01" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>
六、比例(Ratio)
app:layout_constraintDimensionRatio="H,16:9" app:layout_constraintDimensionRatio="W,16:9"
这里的比例指的是占父布局的高度和宽度的比例
七、链条(Chains)
链条适合于横向或者纵向一排的控件的布局方式。
首先要建立一个链条,就是一排控件首位相互约束,以下图
相似的效果的代码像这样,建立了一个链条
<?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="match_parent"> <TextView android:id="@+id/tab1" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/darker_gray" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toLeftOf="@+id/tab2" /> <TextView android:id="@+id/tab2" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_green_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@+id/tab1" app:layout_constraintRight_toLeftOf="@+id/tab3" /> <TextView android:id="@+id/tab3" android:layout_width="0dp" android:layout_height="40dp" android:background="@android:color/holo_red_light" android:gravity="center" android:text="tab1" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintLeft_toRightOf="@+id/tab2" app:layout_constraintRight_toRightOf="parent" /> </android.support.constraint.ConstraintLayout>
效果就像这样
看似效果跟LinearLayout的比重布局很类似,可是它有和LinearLayout不同的效果,就是给链条添加样式。
- CHAIN_SPREAD 元素被分散开(默认样式)
- 在CHAIN_SPREAD模式下,若是一些控件被设置为MATCH_CONSTRAINT,那么控件将会把全部剩余的空间均分后“吃掉”
- CHAIN_SPREAD_INSIDE Chain两边的元素贴着父容器,其余元素在剩余的空间中采用CHAIN_SPREAD模式
- CHAIN_PACKED Chain中的全部控件合并在一块儿后在剩余的空间中居中
4、总结
看完了关于ConstraintLayout布局属性的介绍,是否是感受很是强大,不只有丰富的相对位置约束,还有比例、倾向的设置,具有RelativeLayout
和LinearLayout
两个最经常使用布局的各类优势。关键在性能上也有优点,咱们还有什么理由不尝试呢?
参考连接:
https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout
http://www.javashuo.com/article/p-vvqpebme-bt.html