文章目录
1. ConstraintLayout简介
该layout可以直接在design中进行操作,是比RelativeLayout更强大的Layout。参考文章链接
我们首先需要在app/build.gradle文件中的dependencies中添加ConstraintLayout的依赖,如下所示。
api 'com.android.support.constraint:constraint-layout:1.1.3'
2.使用
2.1 相对定位
普通对齐
这里实现了在ConstrainLayout中的居中,和text2在text1右边的功能。
app:layout_constraintLeft_toRightOf="@+id/text1"的意思就是text2的左边与text1的右边对齐。
正好在整个layout的居中位置,就上下左右都与parent对齐即可。(水平居中就是左右都对齐parent的左右,上下居中就是上下都对其parent的上下)
要注意,如果想要对齐至少要约束两个方向,比如左和上
<TextView
android:id="@+id/text1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="哈哈哈"
android:textSize="18sp"
android:textColor="@color/colorAccent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintRight_toRightOf="parent"
>
</TextView>
<TextView
android:id="@+id/text2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="怕不是个傻子"
android:textColor="@color/colorPrimaryDark"
android:textSize="18sp"
app:layout_constraintLeft_toRightOf="@+id/text1"
app:layout_constraintTop_toTopOf="@+id/text1"
/>
文本基线对齐
两个TextView的高度不一致,但是希望他们文本对齐,就可以采用layout_constraintBaseline_toBaselineOf。
<TextView
android:id="@+id/text1"
.../>
<TextView
android:id="@+id/text2"
...
app:layout_constraintBaseline_toBaselineOf="@id/text1"/>
盗个图,ConstraintLayout相对定位的用法跟RelativeLayout还是比较相似的,下面用一个图来总结相对定位:
2.2 角度定位
角度定位指的是可以用一个角度和一个距离来约束两个空间的中心。
<TextView
android:id="@+id/text2"
...
app:layout_constraintCircle="@id/text1"
app:layout_constraintCircleAngle="120"
app:layout_constraintCircleRadius="180dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
/>
上面例子中的TextView2用到了3个属性:
app:layout_constraintCircle="@+id/text1"
app:layout_constraintCircleAngle=“120”(角度)
app:layout_constraintCircleRadius=“180dp”(距离)
指的是TextView2的中心在TextView1的中心的120度,距离为150dp,
需要注意的是,AS会认为你只用了角度约束还是没有约束,需要补充上普通的位置约束。
效果如下:
2.3 边距
2.3.1 常用margin
ConstraintLayout的边距常用属性如下:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
看起来跟别的布局没有什么差别,但实际上控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的位置,我们两个TextView距离的太近了,我们让他们距离的远一点。
android:layout_marginLeft="20dp"
最后补充一点:对于从左到右的流程,开始=左侧,结束=右侧。对于从右到左的流程,start = right,end = left。
作为Android 4.2对RTL布局的支持的一部分,“开始”和“结束”概念被添加到API Level 17中。
在使用margin的时候要注意两点:
- 控件必须在布局里约束一个相对位置
- margin只能大于等于0
- 如果想设置marginLeft,控件必须约束左边才可以,而不是控件约束了位置就可以。
2.3.2 goneMargin
goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值,属性如下:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
要注意啊!这个属性是约束的控件可见性被设置为gone,不是本身的可见性为gone,也就是说,text2的约束是text1,所以是text1可见性为gone的时候,text2才会使用这个属性!!!!同时会用这个属性代替正常的margin属性。
在text2中这样写,就可以在text1可见性为gone的时候text2有10dp的边距
app:layout_constraintTop_toTopOf="@id/text1"
app:layout_constraintLeft_toRightOf="@id/text1"
app:layout_goneMarginLeft="10dp"
text1可见的时候
text1不可见的时候
2.4 偏移
这里不介绍偏移,因为偏移只会让你在当前的虚拟机上在正确位置,但是如果换了一个不同宽度的手机就会在不同位置。
2.5 链
如果两个或以上控件通过下图的方式约束在一起,就可以认为是他们是一条链(图为横向的链,纵向同理)。
3个TextView相互约束,两端两个TextView分别与parent约束,成为一条链,效果如下:
一条链的第一个控件是这条链的链头,我们可以在链头中设置 layout_constraintHorizontal_chainStyle来改变整条链的样式。chains提供了3种样式,分别是:
spread —— 展开元素 (默认);
spread_inside —— 展开元素,但链的两端贴近parent;
packed—— 链的元素将被打包在一起。
权重链:这时需要将宽度设置为0,然后使用layout_constraintHorizontal_weight(横向)设置权重。这是没有设置权重时的样子。
设置权重后:
2.5 辅助工具
2.5.1 好用的barrier大哥
假如我有三个textview,我想让第三个Textview在左边两个textView的右边,但是左边两个TextView的长度不确定,我没法简单的来leftToRightOf,这个时候,barrier大哥就出现了,barrier大哥又叫屏障。下面是谷歌博客的给出的动态图。
这是全部的xml文件,主要就看我们大哥的就行。constraint_referenced_ids是进行约束的控件id,barrierDirection就是不会超过的方向。这里就是让左边两个控件不超过barrier大哥的右侧。之后我们让第三个TextView在barrier大哥的右边就可以做到以上效果了。
<TextView
android:id="@+id/name"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="姓名"
android:textSize="20sp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
<TextView
android:id="@+id/phone_number"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="手机号789101111111111111"
android:textSize="20sp"
app:layout_constraintLeft_toLeftOf="@id/name"
app:layout_constraintTop_toBottomOf="@id/name"
/>
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="phone_number,name"
/>
<TextView
android:id="@+id/text3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="第三个tv"
app:layout_constraintLeft_toRightOf="@id/barrier"
app:layout_constraintBaseline_toBaselineOf="@id/name"
/>
<Button
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="点我一下呗"
app:layout_constraintTop_toBottomOf="@id/phone_number"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
/>
2.5.2 Group
ConstraintLayout可以使用group来对一些控件进行统一操作。比如可见性。但是点击事件是不可以的。
<android.support.constraint.Group
android:id="@+id/group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:constraint_referenced_ids="phone_number,text3"
/>