ConstraintLayout官方文档 | 郭霖托拉拽 | 代码实现
image.png一、相对位置、相对定位Relative positioning
水平和垂直方向至少得有一个约束
- Horizontal Axis: left, right, start and end sides
- Vertical Axis: top, bottom sides and text baseline
image.png
1.1、相对定位常用属性,
- 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 基线,参考1-3
- layout_constraintStart_toEndOf
- layout_constraintStart_toStartOf
- layout_constraintEnd_toStartOf
- layout_constraintEnd_toEndOf
1.2图例解析
image.png image.png image.png1-1 1-2 1-3
1-1
<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
1-2
<TextView
android:id="@+id/TextView1"
...
android:text="TextView1" />
<TextView
android:id="@+id/TextView2"
...
app:layout_constraintLeft_toRightOf="@+id/TextView1" />
<TextView
android:id="@+id/TextView3"
...
app:layout_constraintTop_toBottomOf="@+id/TextView1" />
1-3
<TextView
android:id="@+id/TextView1"
.../>
<TextView
android:id="@+id/TextView2"
...
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintBaseline_toBaselineOf="@+id/TextView1"/>
二、边距Margins
注意事项:控件在ConstraintLayout里面要实现margin,必须先约束该控件在ConstraintLayout里的位置。在使用margin的时候要注意两点:控件必须在布局里约束一个相对位置,margin只能大于等于0
image.png2.1常用属性
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
//需要下面的约束
//app:layout_constraintLeft_toLeftOf="parent"
//app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
2.2 goneMargin,连接到 GONE 小部件时的边距
说明:goneMargin主要用于约束的控件可见性被设置为gone的时候使用的margin值
常用属性:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
假设TextView2的左边约束在TextView1的右边,并给TextView2设一个app:layout_goneMarginLeft="10dp",代码如下:
<android.support.constraint.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/TextView1"
.../>
<TextView
android:id="@+id/TextView2"
...
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_goneMarginLeft="10dp"
/>
</android.support.constraint.ConstraintLayout>
效果如下2-1,TextView2在TextView1的右边,且没有边距。这个时候把TextView1的可见性设为gone,TextView1消失后,TextView2有一个距离左边10dp的边距。效果如下:2-2
image.png 2-1 image.png2-2
三、居中和偏移Centering positioning and bias
居中:
image.png<android.support.constraint.ConstraintLayout ...>
<Button android:id="@+id/button" ...
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent
app:layout_constraintBottom_toBottomOf="parent
app:layout_constraintTop_toTopOf="parent"/>
</>
居中
偏移:
说明:赋一个范围为 0-1 的值,假如赋值为0,则TextView1在布局的最左侧,假如赋值为1,则TextView1在布局的最右侧,假如假如赋值为0.5,则水平居中,水平竖直方向value="0.3"相当于weight百分比占比
常见属性:
- layout_constraintHorizontal_bias
- layout_constraintVertical_bias
image.png
<android.support.constraint.ConstraintLayout ...>
<Button android:id="@+id/button" ...
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent/>
</>
写上具体的偏移值:
上面TextView1在水平居中后使用layout_marginLeft="100dp"向右偏移了100dp
image.png<TextView
android:id="@+id/TextView1"
...
android:layout_marginLeft="100dp"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent" />
四、角度定位Circular positioning (Added in 1.1)
说明:您可以相对于另一个小部件中心以某个角度和距离约束小部件中心。这允许您将一个小部件放置在一个圆圈上(见图 6)。
角度从垂直方向顺时针,类似钟表。
相关属性:
image.png
layout_constraintCircle
: references another widget idlayout_constraintCircleRadius
: the distance to the other widget centerlayout_constraintCircleAngle
: which angle the widget should be at (in degrees, from 0 to 360)
<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
app:layout_constraintCircle="@+id/buttonA"
app:layout_constraintCircleRadius="100dp"
app:layout_constraintCircleAngle="45"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
/>
Visibility behavior
尺寸约束Dimensions constraints
android:minWidth
set the minimum width for the layoutandroid:minHeight
set the minimum height for the layoutandroid:maxWidth
set the maximum width for the layoutandroid:maxHeight
set the maximum height for the layout
The dimension of the widgets can be specified by setting the android:layout_width
and android:layout_height
attributes in 3 different ways:
- 指定尺寸:Using a specific dimension (either a literal value such as
123dp
or aDimension
reference) - 使用wrap_content,让控件自己计算大小,Using
WRAP_CONTENT
, which will ask the widget to compute its own size - 使用 0dp (MATCH_CONSTRAINT),Using
0dp
, which is the equivalent of "MATCH_CONSTRAINT
"
<TextView
android:id="@+id/TextView4"
android:layout_width="0dp"
android:layout_height="110dp"
android:background="@color/black"
android:layout_marginLeft="30dp"
app:layout_constraintDimensionRatio="w,1:1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
image.png
宽高比
当宽或高至少有一个尺寸被设置为0dp时(并且当一个0为0时另外一个至少是一个具体的数值,不能为****wrap_content,不然看着没有啥效果),可以通过属性layout_constraintDimensionRatio设置宽高比
- app:layout_constraintDimensionRatio="H,2:3"指的是 高:宽=2:3
- app:layout_constraintDimensionRatio="W,2:3"指的是 宽:高=2:3
<TextView
android:id="@+id/TextView4"
android:layout_width="0dp"
android:layout_height="110dp"
android:background="@color/black"
app:layout_constraintDimensionRatio="w,1:1" 正方形
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
链:Chains
- 链在单个轴(水平或垂直)上提供类似组的行为。另一个轴可以独立约束。
- 如果一组小部件通过双向连接链接在一起,则它们被认为是一个链(显示了一个最小链,具有两个小部件。
链头:Chain heads
链由设置在链的第一个元素(链的“头”)上的属性控制:头部是水平链最左边的小部件,垂直链是最顶部的小部件。
image链中的边距Margins in chains
<TextView
android:id="@+id/TextView11"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#685454"
android:text="ff0000"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/TextView12"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/TextView12"
app:layout_constraintTop_toTopOf="parent"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#00ff00"
android:text="00ff00"
app:layout_constraintLeft_toRightOf="@+id/TextView11"
app:layout_constraintRight_toLeftOf="@+id/TextView13"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/TextView13"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#0000ff"
android:text="0000ff"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@+id/TextView12"
app:layout_constraintRight_toRightOf="parent" />
- CHAIN_SPREAD —— 展开元素 (默认);均等分
- CHAIN_SPREAD_INSIDE —— 展开元素,但链的两端贴近parent;
- CHAIN_PACKED —— 链的元素将被打包在一起。
权重:Weighted chains
- layout_constraintHorizontal_weight
- layout_constraintVertical_weight
image.png
<Button
android:id="@+id/sbBtn"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="xxxx"
app:layout_constraintEnd_toStartOf="@+id/sbBtn01"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/sbBtn01"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
app:layout_constraintEnd_toStartOf="@+id/sbBtn02"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/sbBtn"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/sbBtn02"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="xxxxxxxxxxxxxxxxxxxx"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/sbBtn01"
app:layout_constraintTop_toTopOf="parent" />
Barrier屏障
使用场景:假设有3个控件ABC,C在AB的右边,但是AB的宽是不固定的,这个时候C无论约束在A的右边或者B的右边都不对。当出现这种情况可以用Barrier来解决。Barrier可以在多个控件的一侧建立一个屏障,如下所示:
image.png属性说明:其中,app:constraint_referenced_ids="btn_a,btn_b"
这句指定这个Barrier是用来控制id为btn_a和btn_b的两个控件。而app:barrierDirection="end"
这句等于在这两个控件的右端设置一道“屏障”。
最后,我们让控件C依赖于这个Barrier。注意这句:app:layout_constraintLeft_toLeftOf="@id/barrier"
** app:barrierDirection="right",值有多个可调节,比如start,bottom , top**
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="btn_a,btn_b" />
<Button
android:id="@+id/btn_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="200dp"
android:text="这是控件A,我比较宽"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="这是控件B"
app:layout_constraintLeft_toLeftOf="@id/btn_a"
app:layout_constraintTop_toBottomOf="@id/btn_a" />
<Button
android:id="@+id/btn_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="200dp"
android:text="这是控件C"
app:layout_constraintLeft_toLeftOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent" />
Group:控制一系列id相关控件的显示隐藏状态
在xml文件中设置 android:visibilitys属性
androidx.constraintlayout.widget.Group中使用****app:constraint_referenced_ids="btn_a,btn_b,btn_c" 可将相关id可见属性****android:visibility="visible"****进行显示隐藏显示。
<!--计数Group-->
<androidx.constraintlayout.widget.Group
android:id="@+id/count_group"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="visible"
app:constraint_referenced_ids="btn_a,btn_b,btn_c" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="btn_a,btn_b" />
<Button
android:id="@+id/btn_a"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="200dp"
android:text="这是控件A,我比较宽我比较宽我比较宽"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btn_b"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="30dp"
android:text="这是控件B"
app:layout_constraintLeft_toLeftOf="@id/btn_a"
app:layout_constraintTop_toBottomOf="@id/btn_a" />
<Button
android:id="@+id/btn_c"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="200dp"
android:text="这是控件C"
app:layout_constraintLeft_toLeftOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent" />
代码控制:****在代码中通过group.setVisibility()方法来设置
但是我在实践中发现,当我在代码中调用group.setVisibility()来显示或隐藏group中的一组控件时,这个方法并没有生效。通过查看源码发现,Group更新他成员的可见性状态是在 updatePreLayout(),而这个方法最终是在ConstraintLayout中通过updateHierarchy()方法调用的
那么我们就可以在设置可见性之后再调用group.requestLayout(),而requestLayout()方法会导致View的onMeasure、onLayout、onDraw方法被调用,这样我们就可以立即改变group中控件的可见性了。
if (recIsClick) {
countGroup.setVisibility(View.VISIBLE);
} else if (recIsClick) {
countGroup.setVisibility(View.INVISIBLE);
}
countGroup.requestLayout();
Placeholder占位符
Placeholder指的是占位符。在Placeholder中可使用setContent()设置另一个控件的id,使这个控件移动到占位符的位置。新建一个Placeholder约束在屏幕的左上角,新建一个TextView约束在屏幕的右上角,在Placeholder中设置 app:content="@+id/textview",这时TextView会跑到屏幕的左上角。举个例子:
<androidx.constraintlayout.widget.Placeholder
android:id="@+id/placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:content="@+id/textview"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
<TextView
android:id="@+id/textview"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="#cccccc"
android:padding="16dp"
android:text="TextView"
android:textColor="#000000"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintBottom_toBottomOf="parent" />
Guideline
说明:Guildline像辅助线一样,在预览的时候帮助你完成布局(不会显示在界面上)。
使用属性:
- android:orientation 垂直vertical,水平horizontal
- layout_constraintGuide_begin 开始位置
- layout_constraintGuide_end 结束位置
- layout_constraintGuide_percent 距离顶部的百分比(orientation = horizontal时则为距离左边)
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline"
app:layout_constraintGuide_begin="250dp"
android:orientation="vertical"/>
<androidx.constraintlayout.widget.Guideline
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline2"
app:layout_constraintGuide_percent="0.1"
android:orientation="vertical"/>
<Button
android:text="Button_guideline"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button"
android:background="#ff0000"
app:layout_constraintLeft_toLeftOf="@+id/guideline"
android:layout_marginTop="16dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
效果图:
image.png
网友评论