ConstrainLayout官方文档
https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout.html
目录
2、Circular positioning (Added in 1.1) 圆形定位
3、Dimensions constraints (尺寸约束)
ConstraintLayout常用标签
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
layout_constraintStart_toEndOf
layout_constraintStart_toStartOf
layout_constraintEnd_toStartOf
layout_constraintEnd_toEndOf
以最后一个下划线区分,layout_constraintXXX 代表当前控件 toXXXOf代表的是相比较的控件/父布局
举个简单的例子
A位于父布局的中间位置,四条边都约束于parent
B控件 左边约束于A控件扽左边,右边约束于A控件的右边,上边约束于A控件的下边。
<Button
android:text="A"
android:layout_width="151dp"
android:layout_height="120dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/button"
/>
<Button
android:text="B"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
app:layout_goneMarginTop="20dp"
app:layout_constraintEnd_toEndOf="@+id/button"
app:layout_constraintStart_toStartOf="@+id/button"
app:layout_constraintTop_toBottomOf="@+id/button"
android:layout_marginTop="144dp"
app:layout_constraintHorizontal_bias="1.0"/>
细心的你可能看到了B设置了marginTop,144dp,那 layout_goneMarginTop代表什么意思呢?
它的意义在于如果A控件可见行设为Gone了,那么B设置的margin值全部失效,这个layout_goneMargin可以重新为B控件设置新的margin值,可以把它当作layout_margin的备胎,不信你可以试试看哦。
左右拖动B控件,可调节 app:layout_constraintHorizontal_bias 大小,控制B控件所处位置,默认值是0.5,位于A控件中间的位置。
其他的约束都好理解,那layout_constraintBaseline_toBaselineOf是什么鬼呢?
这个标签是用来设置文字对齐的,看图说话
<TextView
android:text="文字1"
android:layout_width="99dp"
android:layout_height="107dp"
android:id="@+id/textView"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintStart_toStartOf="parent"
/>
<TextView
android:text="文字2"
android:layout_width="109dp"
android:layout_height="79dp"
android:id="@+id/textView2"
app:layout_constraintEnd_toEndOf="parent"
android:layout_marginRight="92dp"
android:layout_marginEnd="92dp"
app:layout_constraintBaseline_toBaselineOf="@+id/textView"/>
2、Circular positioning (Added in 1.1) 圆形定位
官方解释 You can constrain a widget center relative to another widget center, at an angle and a distance.
可以理解成 将一个控件的中心以一定的角度和距离约束到另一个控件的中心,相当于在一个圆上放置一个控件。
看图说话
有下面3个属性可用
layout_constraintCircle
: 所引入的控件idlayout_constraintCircleRadius
: 圆半径layout_constraintCircleAngle
: 偏移角度(in degrees, from 0 to 360)
大家看下面这个用户头像布局怎么做?
<ImageView
android:id="@+id/image"
android:layout_width="60dp"
android:layout_height="60dp"
android:src="@mipmap/img_logo_personal_center"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="120dp"
/>
<TextView
android:id="@+id/vip"
android:layout_width="30dp"
android:text="VIP"
android:textColor="#f00"
android:textStyle="bold"
android:textSize="18sp"
android:layout_height="30dp"
app:layout_constraintCircle ="@id/image"
app:layout_constraintCircleRadius="35dp"
app:layout_constraintCircleAngle="135"
/>
3、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
当控件的dimensions(宽高维度)设置为WRAP_CONTENT时,可使用上面的标签,限定最大、最小尺寸。
1、 控件尺寸约束
设置android:layout_width
and android:layout_height
attributes in 3 different ways:
1、固定尺寸 (eg:20dp)
2、WRAP_CONTENT (它要求控件计算自己的大小)
3、 0dp
, 也就是 "MATCH_CONSTRAINT
"
a:wrap_content
b: 0dp
c:设置了边距的 0dp
官方不建议使用MATCH_PARENT,可以用MATCH_CONSTRAINT代替。
2、 enforcing constraints (强约束)
当一个控件设为wrap_content时,再添加约束尺寸是不起效果的。如需生效,需要设置如下属性为true:
- app:layout_constrainedWidth=”true|false”
- app:layout_constrainedHeight=”true|false”
3、MATCH_CONSTRAINT dimensions (Added in 1.1)
当维度设置为时MATCH_CONSTRAINT
,默认行为是让生成的大小占用所有可用空间。有几个额外的修饰符可用:
layout_constraintWidth_min
和layout_constraintHeight_min
:将设置此维度的最小尺寸layout_constraintWidth_max
和layout_constraintHeight_max
:将设置此维度的最大尺寸layout_constraintWidth_percent
和layout_constraintHeight_percent
:将设置此维度的大小为父级的百分比
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintWidth_min="200dp"
app:layout_constraintHeight_min="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constrainedWidth="true"
app:layout_constrainedHeight="true"
android:id="@+id/button4"/>
<Button
android:text="Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintWidth_max="200dp"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/button4"/>
4、Percent dimension
要使用百分比,您需要设置以下内容:
维度应该设置为 MATCH_CONSTRAINT
(0dp)- 默认值设置百分比percent
app:layout_constraintWidth_default="percent"
orapp:layout_constraintHeight_default="percent"
设置占用父布局百分比 layout_constraintWidth_percent
orlayout_constraintHeight_percent
设置为介于0和1之间的值
5、Ratio (可设置控件宽高比例)
使用这个属性有个条件 :您至少需要将一个约束维度设置为0dp
(即MATCH_CONSTRAINT
),并将该属性layout_constraintDimensionRatio
设置为给定比率。
下面我们设置一个Button的宽高比为3:1
<Button
android:text="Button"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintDimensionRatio="3:1"
android:id="@+id/button5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
比例可以表示为:
- 浮点值,表示宽度和高度之间的比率
- “宽度:高度”形式的比率
如果两个维都设置为MATCH_CONSTRAINT
(0dp),您也可以使用比率。在这种情况下,系统设置满足所有约束条件的最大尺寸并保持指定的宽高比。为了约束一个基于另一个维的特定边,你可以预先附加W,
“或者H,
分别限制宽度或者高度。
<Button
android:text="Button"
android:layout_width="0dp"
android:layout_height="0dp"
app:layout_constraintDimensionRatio="H,4:1"
android:id="@+id/button5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintBottom_toBottomOf="parent"/>
这里限定高度,为宽度的的1/4
4、Chains (链)
有两种链,水平或垂直
一个链包含了多个视图,它允许链中的视图共享空间,并控制可用空间在它们之间如何分配。该效果与 LinearLayout
的 Weiget
类似,但是链的作用远远超过它。
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="137dp"
android:id="@+id/button9"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@+id/button10"/>
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="137dp"
android:id="@+id/button10"
app:layout_constraintStart_toEndOf="@+id/button9"
app:layout_constraintEnd_toStartOf="@+id/button11"/>
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
tools:layout_editor_absoluteY="137dp"
android:layout_marginRight="16dp"
android:layout_marginEnd="16dp"
app:layout_constraintEnd_toEndOf="parent"
android:id="@+id/button11"
app:layout_constraintStart_toEndOf="@+id/button10"
/>
链头是指链中第一个控件 ,头是水平链最左边的部件,也是垂直链最顶端的部件。
设置链式Style
为链条的第一个元素设置属性layout_constraintHorizontal_chainStyle
或layout_constraintVertical_chainStyle
链条的行为将根据指定的样式(默认为CHAIN_SPREAD
)更改。
CHAIN_SPREAD
- 元素将被分散(默认样式)CHAIN_SPREAD_INSIDE
- 与CHAIN_SPREAD
类似,但链条的端点不会被分散Weighted chain
- 在CHAIN_SPREAD
模式下,如果某些小部件设置为MATCH_CONSTRAINT
,它们将拆分可用空间CHAIN_PACKED
- 链条的元素将被包装在一起。子的水平或垂直偏向属性将影响打包元素的位置
加权链(Weighted chain)
与LinearLayout的权重基本一致
链的默认行为是在可用空间中均匀分布元素。如果一个或多个元素正在使用MATCH_CONSTRAINT
,他们将填充可用的空白区域(在它们之间平均分配)。属性layout_constraintHorizontal_weight
和layout_constraintVertical_weight
将控制如何将空间利用的元素之间进行分配MATCH_CONSTRAINT
。例如,在包含两个使用MATCH_CONSTRAINT
元素的链中,第一个元素的权重为2,第二个权重为1,第一个元素占用的空间将是第二个元素的两倍。
在链中设置边距
在链中的元素上使用边距时,边距是可加的:
- 例如在水平链上,如果一个元素定义了10dp的右边距,而下一个元素的左边距为5dp,则这两个元素之间的结果边距将为15dp
- 在计算链条用于放置物品的剩余空间时,会将物品加上其边距一起考虑,剩余空间不包含边距。
5、Guideline
Guidelines
是一条对实际显示界面不可见的线。用处是帮助我们的控件增加约束,可以设置水平或垂直方向。
Guideline 具有以下的三种定位方式
layout_constraintGuide_begin 距离父容器起始位置的距离(左侧或顶部)
layout_constraintGuide_end 距离父容器结束位置的距离(右侧或底部)
layout_constraintGuide_percent 距离父容器宽度或高度的百分比
比如我们想让Button位置位于右下角,举例底部和容器右边 只有20%距离
<androidx.constraintlayout.widget.Guideline android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline1"
android:orientation="vertical"
app:layout_constraintGuide_percent="0.8"/>
<androidx.constraintlayout.widget.Guideline android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/guideline2"
android:orientation="horizontal"
app:layout_constraintGuide_percent="0.8"/>
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button7"
app:layout_constraintRight_toRightOf="@+id/guideline1"
app:layout_constraintLeft_toLeftOf="@+id/guideline1"
app:layout_constraintTop_toTopOf="@id/guideline2"
app:layout_constraintBottom_toBottomOf="@+id/guideline2"
/>
5、Barrier (屏障)
Barrier,直译为障碍、屏障。在约束布局中,可以使用属性constraint_referenced_ids
属性来引用多个带约束的组件,从而将它们看作一个整体,Barrier 的介入可以完成很多其他布局不能完成的功能
对 Barrier 可以使用的属性有:
barrierDirection:设置 Barrier 所创建的位置。可设置的有:bottom、end、left、right、start、top。
constraint_referenced_ids:设置 Barrier 引用的控件。可设置多个,设置的方式是:id, id。(无需加 @id/)
barrierAllowsGoneWidgets:默认为 true,即当 Barrier 引用的控件被 GONE 掉时,则 Barrier 默认的创建行为是在已 GONE 掉控件的已解析位置上进行创建。如果设置为 false,则不会将 GONE 掉的控件考虑在内。
当在 TextView1和TextView2 控件的大小都不确定的情况下, TextView3 以谁作为约束对象都不对。如果以 TextView1 作为约束对象,那么当 TextView2 的宽度过宽时就会被遮挡,同理以 TextView2 作为约束也是如此。
那么此时,Barrier(屏障)就派上用场了。这是个非常好用的东东,和 GuideLine 一样,它是一个虚拟的 View,对界面是不可见的。目的就是辅助布局。
<TextView
android:text="你好"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/textView1"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="16dp"
/>
<TextView
android:text="它是一个虚拟的 View"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
android:id="@+id/textView2"
app:layout_constraintTop_toBottomOf="@+id/textView1"
android:layout_marginTop="44dp"/>
<TextView
android:text="看我的位置在哪里啊"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintLeft_toRightOf="@+id/barrier"
android:id="@+id/textView3"/>
<androidx.constraintlayout.widget.Barrier
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/barrier"
app:constraint_referenced_ids="textView1,textView2"
app:barrierDirection="right"/>
6、Group
Group 的作用就是控制一组控件的可见性。其可使用到的属性为:
- constraint_referenced_ids:指定所引用控件的 id。
<androidx.constraintlayout.widget.Group
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone"
app:constraint_referenced_ids="textView1, textView2" />
7、placeholder 占位
Placeholder(占位符)是一个虚拟对象,作用和它的名字一样,就是占位。
当放置好 Placeholder 后,可以通过 setContentId() 方法将占位符变为有效的视图。如果视图已经存在于屏幕上,那么视图将会从原有位置消失。配合过度动画,可达到很好的视觉效果。
<ImageView
android:id="@+id/imageHead"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@mipmap/img_logo_personal_center"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<androidx.constraintlayout.widget.Placeholder
android:id="@+id/placeholder"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
点击头像,图片出现在占位图中
imageHead.setOnClickListener {
placeholder.setContentId(R.id.imageHead)
}
8、优化器
可以通过将标签app:layout_optimizationLevel元素添加到ConstraintLayout来决定应用哪些优化。
- none:不应用优化
- standard:默认。仅优化直接和障碍约束
- direct:优化直接约束
- barrier:优化障碍约束
- chain:优化链条约束
- dimensions: 优化维度测量,减少匹配约束元素的度量数量在设置值时,
可以设置多个,如:
app:layout_optimizationLevel="direct|barrier|dimensions"
9、ConstraintSet运用
This class contains the different attributes specifying how a view want to be laid out inside a ConstraintLayout
. For building up constraints at run time, using ConstraintSet
is recommended.
上面英文出自官方解释,运行中如何更改布局中控件的约束,建议使用ConstraintSet。
首先看下ConstraintSet是如何运用的
1、写一个简单布局,两个Button
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/constraintLayout"
xmlns:app="http://schemas.android.com/apk/res-auto">
<Button
android:text="Button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button1"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginTop="40dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
<Button
android:text="我要移动了"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:id="@+id/button2"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"/>
</androidx.constraintlayout.widget.ConstraintLayout>
对上面的Button设置一个点击事件,我们要改变下面Button的位置。
val set = ConstraintSet()
button1.setOnClickListener {
set.clone(this, R.layout.activity_main)//复制一份父布局的约束
// 设置组件之间的约束
set.connect(R.id.button2, ConstraintSet.LEFT, R.id.button1, ConstraintSet.LEFT)
set.connect(R.id.button2, ConstraintSet.RIGHT, R.id.button1, ConstraintSet.RIGHT)
set.connect(R.id.button2, ConstraintSet.TOP, R.id.button1, ConstraintSet.BOTTOM)
// set.centerHorizontally(R.id.button15, ConstraintSet.PARENT_ID) //设置btn水平剧中于父布局parent
// 设置btn的高度,宽度
set.constrainHeight(R.id.button2, 100)
set.constrainWidth(R.id.button2, 400)
TransitionManager.beginDelayedTransition(constraintLayout)//设置一个动画
set.applyTo(constraintLayout)//.最后一步 ,apply一下使设置生效
效果图
这里就介绍完了,深夜撸码,实属不易,感谢收看!
参考
https://developer.android.google.cn/reference/android/support/constraint/ConstraintLayout.html
https://blog.csdn.net/airsaid/article/details/79052011
https://blog.csdn.net/guolin_blog/article/details/53122387