最近几个月终于有大把时间总结这两年来所学,荣幸之至
2019.5.19
前言
- 在ConstraintLayout之前,布局通常使用LinearLayout和RelativeLayout比较多,用熟悉了也感觉还比较不错。但是如果你的UI太复杂,使用相对布局会有大量的嵌套,会造成大量的性能浪费和维护成本。
- ConstraintLayout 的使用逻辑非常简单,可以完全替代RelativeLayout布局,不包含层层嵌套,写布局文件时可能也没那么痛苦。痛苦?!
对应内容的练手项目
目录
本文包含1.1-1.5的内容
2.1-2.6在:ConstraintLayout 使用入门(二)
- 1 基本操作
- 1.1 相对位置布局
- 1.2 整体位置布局
- 1.3 约束比例
- 1.4 文字基准线对齐
- 1.5 圆心布局(原文叫 Circular positioning)
- 2 进阶操作
- 2.1 View的内容约束 constrainedWidth
- 2.2 约束偏移量 Bias
- 2.3 约束链 Chain Style
- 2.4 宽高比
- 2.5 百分比布局
- 2.6 参考线
- 3.Helper类
- 3.1 Group
- 3.2 Layer
1.基本操作
详细介绍View基本的放置,包括放置的上下左右(top,bottom,start,end,left,right
),间距(margin
)这两个约束类型
1.1 相对位置布局
- 先来一个最简单的实现。
实现居中于整个root View的布局,核心使用下面四行即可
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
效果是这个样子(那个蓝色弹簧一样的四根线是studio给的效果渲染)
图一:居中布局挑其中一行来理解一下意义,其他的类比。
比如:app:layout_constraintStart_toStartOf="parent"
需要关注的重点参数有三个,如下图,画了红圈
第一个Start
表示自己的start;
第二个Start
表示约束对象(也就是parent)的start;
parent
表示约束对象id。
关于方位的参数包含Start
在内,还有Start、End、Top、Bottom、Left、Right
,(另外有一个baseLine
基准线,后面再讲)。
他们的关系我就直接用谷歌官网的图了,如下图
top bottom
:表示view的顶部和底部
start end
:表示view的开始和结束
left right
:表示view的左边和右边
这里可能大家就有点儿小疑问了,这个start
和letf
,以及end
和right
感觉是一样的啊,有啥区别?
对于从左往右看的文字或者图片(看图还分方向?)来说,start
就是letf
、end
就是right
,没有区别;但是对于从右往左看的,比如阿拉伯语,他们的start
就是right
、end
就是letf
。
所以,我们平时使用的话,就直接用start
和end
就行了,left
和right
基本可以不用。
关于方位的,包括上面讲到的四个以外,还有其他的常用语句
layout_constraintLeft_toLeftOf
layout_constraintLeft_toRightOf
layout_constraintRight_toLeftOf
layout_constraintRight_toRightOf
layout_constraintTop_toTopOf
layout_constraintTop_toBottomOf
layout_constraintBottom_toTopOf
layout_constraintBottom_toBottomOf
layout_constraintBaseline_toBaselineOf
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
看着好像有点儿多,总的来说就是四个方向的组合,然后意思也很好理解,比如 layout_constraintStart_toEndOf
就表示把控件的左边和约束控件的右边绑定起来。
形象一点儿来说,我们对ViewA设置了 layout_constraintStart_toEndOf=@id/ViewB
,就表示ViewA的start
绑定到了ViewB的end
,像这样子
引申一下,如果你想让ViewA 像图四一样完全位于ViewB的右侧,那么你还需要约束ViewB的start,top,bottom
,ViewA的top,bottom,end
。
- 理解了上面的基本方位以后,我们来看看下面一个约束类型 -- margin
- margin 表示相对于上面讲到的六个方位(
top,bottom,left,right,start,end
)的距离,对应下面六个效果:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
这个就很好理解了,就是正对于约束方向的距离。举个例子,有一个ViewA,放置于页面的左侧且垂直方向居中,像这样
图五:左侧垂直居中现在想让它离左侧边距80dp,就只需呀加上 android:layout_marginStart="80dp"
,这样子就可以了,然后它的效果是这样子的。
这里的margin值针对的是相对于约束对象,比如上面的图四(下面),我们队ViewA设置了android:layout_marginStart="80dp"
,那么ViewA和ViewB的间距就会变为80dp。
1.2整体位置布局
这一部分是针对上面的一个小实践,现在,我们要完成下图中左上角红色框中的布局。
我这里倾向于简单分析一下,然后直接把结果贴上来,大家可以体会一下,然后自己练习一下,很好理解的。
简化一下,我们视图分成三部分,一个是左侧的ImageView,一个是右方上侧的TextView,编号为TextViewA,一个是右方下侧的TextView,编号为TextViewB。TextViewA和TextViewB垂直居中对齐,然后一起和ImageView水平居中对齐,同时两个TextView和ImageView水平方向还有一定的间距(margin)。
- 对于ImageView,需要建立
top,bottom,start
三个方向的约束,同时start
方向需要有marginStart
,marginStart
的值自己设置一下就行。贴一下效果图
- 对于两个TextView,TextViewA和TextViewB需要相互约束,同时和ImageView约束。为了方便看,我把ImageView拉长了,还把右侧的解析图也截图了出来,来看一下布局的效果:
对着图九简单理解一下:
对ImageView,布局属性的设置如下
android:id="@+id/imageView"
...
android:layout_marginStart="50dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
对于TextViewA,布局属性的设置如下
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="@+id/imageView"
app:layout_constraintBottom_toTopOf="@id/TextViewB"
app:layout_constraintStart_toEndOf="@id/imageView"
app:layout_constraintEnd_toEndOf="@id/TextViewB"
对于TextViewB,布局属性的设置如下
android:layout_marginStart="20dp"
app:layout_constraintTop_toBottomOf="@+id/TextViewA"
app:layout_constraintBottom_toBottomOf="@+id/imageView"
app:layout_constraintStart_toEndOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="@id/TextViewA"
按照上面的设置好以后,不管怎么移动或者缩放ImageView,两个TextView始终和左侧的ImageView水平居中对齐
图10:最终效果图1.3 约束比例
- 充满约束
充满约束是指把View的内容充满整个约束条件,只需要把宽度或者高度设置为0dp就行了。 注意一下:“充满约束条件”[match_constraint]的意思 和“充满父布局”[match_parent]是不一样的,“充满约束条件”是指在同级View的约束条件下,自己可以的最大尺寸,“充满父布局”是指充满父ViewGroup的空间。
- 约束比例
- 水平方向:
layout_constraintHorizontal_weight
- 垂直方向:
layout_constraintVertical_weight
比如我们这里有一个需求,想要两个按钮A、B的width比例为2:1,使用 layout_constraintHorizontal_weight
就可以解决。
方法如下:
将A和B的layout_width
设置为0dp
对A设置app:layout_constraintHorizontal_weight="2"
对B设置app:layout_constraintHorizontal_weight="1"
最后,分别对A B的top,bottom,start,end
四个方向的约束,效果就像这个样子。
1.4 文字基准线对齐
app:layout_constraintBaseline_toBaselineOf="id"
实现两个textView的文本对齐。
我们写两个TextView,让其居中对齐,像这样子:
在右边的TextView中加入app:layout_constraintBaseline_toBaselineOf="@id/hello"
,就变成了文字基准线对齐:
1.5 圆心布局(原文叫 Circular positioning)
这种布局方式是角度和距离来约束两个View的中心关系,有下面三个约束条件
app:layout_constraintCircle="id"
app:layout_constraintCircleAngle="angle"
app:layout_constraintCircleRadius="distance"
id
:表示需要约束的View
angle
:表示相对角度,这个角度是以水平竖直方向开始计算,顺时针递加
distance
:表示距离
这里的图示我就直接用Google官方的图了
举个例子:
<CircularSunView android:id="@+id/sun" ... />
<CircularEarthView android:id="@+id/earth" ...
app:layout_constraintCircle="@+id/sun"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintCircleAngle="45" />
我们重点关注最后三行属性设置。效果图如下:
图15圆心布局效果说明一下:CircularSunView和CircularEarthView是两个自定义的View,显示sun和earth的形状(因为我找了一圈儿,纯色的图不好找,然后非纯色的图感觉不是很符合我这种清新脱俗的风格)
image
1.1--1.5都是非常基本的操作,学会了这些,很多布局都能很得心应手的搞定了。下面一节继续介绍一些比较高能又常用的技巧。
另外,为了避免看文章枯燥,我准备了一个练手项目,看完以后可以下载下来练习练习。
再另外,以上都是自己平时所学整理,如果有错误,欢迎留言或者添加微信批评指出,一起学习,共同进步,爱生活,爱技术。
网友评论