总结下ConstraintLayout的使用:
因为ConstraintLayout采用约束的方式控制控件的位置,所以至少要保证水平和垂直方向都至少有一个约束才能确定控件的位置。
例如让TextView的顶部和界面顶部对齐,左部和界面左部对齐。
使用start和end来表示左和右是为了考虑别的国家的习惯,有的国家开始方向是右,所以使用start和end可以兼容这种情况。
记忆的思路是:该控件的??方向在哪个控件的??方向。
再以TextView为例:
app:layout_constraintTop_toTopOf="parent" TextView的顶部和parent的顶部对齐
app:layout_constraintBottom_toBottomOf="parent" TextView的底部和parent的底部对齐
app:layout_constraintLeft_toLeftOf="parent" TextView的左边和parent的左边对齐
app:layout_constraintRight_toRightOf="parent" TextView的右边和parent的右边对齐
app:layout_constraintStart_toStartOf="parent" TextView的开始位置和parent的开始位置对齐
app:layout_constraintEnd_toEndOf="parent" TextView的结束位置和parent的结束位置对齐
app:layout_constraintTop_toBottomOf="parent" TextView的顶部位置在parent的底部位置
app:layout_constraintStart_toEndOf="parent" TextView的开始位置在parent的结束为止
通过layout_constraintBaseline_toBaselineOf来实现两个文本的基线对齐。
需要实现一个控件在某个控件的某个角度的位置,ConstraintLayout提供了角度位置相关的属性。
app:layout_constraintCircle="" 目标控件id
app:layout_constraintCircleAngle="" 对于目标的角度(0-360)
app:layout_constraintCircleRadius="" 到目标中心的距离
Text2 在 Text1的45度方向,距离为100dp
让控件在父布局的水平方向或垂直方向的百分之多少的位置
app:layout_constraintHorizontal_bias="parent" 根据父布局的 水平偏移 取值范围是0-1的小数
app:layout_constraintVertical_bias="parent" 根据父布局的 垂直偏移 取值范围是0-1的小数
控件Text_1在父布局水平方向偏移0.2(20%),垂直方向偏移0.8(80%)
控件Text_2在水平方向偏移0.2(20%),垂直方向偏移0.5(50%)
ConstraintLayout使用goneMargin属性,当依赖的目标view隐藏时,该属性生效,例如B被A依赖约束,当B隐藏时B会缩成一个点,自身的margin效果失效,A设置的goneMargin就会生效。
当Text_1显示时,Text_2goneMargin属性不生效。
当Text_1隐藏之后,Text_1会缩成一个点,Text_2设置的goneMargin就会生效,start:100dp,bottom:200dp
在ConstraintLayout中有尺寸限制的属性,可以用来限制最大、最小宽高度,这些属性只有在给出的宽度或高度为wrap_content时才会生效。
android:minWidth="" 设置view的最小宽度
android:minHeight="" 设置view的最小高度
android:maxWidth="" 设置view的最大宽度
android:maxHeight="" 设置view的最大高度
TextView 的最小宽度和最大宽度,最小高度和最大高度。
设置view的大小除了wrap_content、指定尺寸、match_parent外,还可以设置为0dp(MATCH_CONSTRAINT),并且0dp的作用会根据设置的类型而产生不同的作用,进行设置类型的属性是layout_constraintWidth_default和layout_constraintHeight_default,取值可为spread、percent、wrap。具体的属性及示例如下:
app:layout_constraintWidth_default="spread|percent|wrap"
app:layout_constraintHeight_default="spread|percent|wrap"
下面的TextView的宽度适应了所有有效的约束空间,左右留出100dp,所以默认的效果是:自身View的宽度填充满剩余空间。
percent模式将自身view的尺寸设置为父布局尺寸的一定比例,下面将TextView所展示的是宽度设置为父布局宽度的0.7(70%,取值是0-1的小数),该模式需要配合layout_constraintWidth_percent使用。
两个控件作为对比,Text1宽度设置为wrap_content,宽度适应内容大小,并且设置了margin,但是显然宽度已经超过margin的设置值了,Text2宽度设置为0dp wrap模式,宽度适应内容大小,并且不会超过margin的设置值,也就是不会超过约束限制,这就是这两者的区别。
从下面的例子可以发现:wrap会影响到 TextView内容的排列。
Google还提供了两个属性用于强制约束:
app:layout_constrainedWidth="true|false"
app:layout_constrainedHeight="true|false"
将Text1设置了强制约束,展示出的效果和Text2就一样了。
0dp还有一些其他的独特属性用于设置尺寸的大小限制
app:layout_constraintWidth_min="" 0dp下,宽度的最小值
app:layout_constraintHeight_min="" 0dp下,高度的最小值
app:layout_constraintWidth_max="" 0dp下,宽度的最大值
app:layout_constraintHeight_max="" 0dp下,高度的最大值
ConstraintLayout中可以对宽高设置比例,前提是至少有一个约束维度设置为0dp,这样比例才会生效,该属性可使用两种设置:
app:layout_constraintDimensionRatio="2:1" 宽高比例2:1
将许多个控件在水平或者垂直方向,形成一条链,用于平衡这些控件的位置,形成一条链要求链中的控件在水平或者垂直方向,首尾互相约束,这样就可以形成一条链。
Text_1、Text_2、Text_3,三个控件在水平方向上首尾互相约束,这样就形成了一条水平链,默认的模式是spread,均分剩余空间,使用layout_constraintHorizontal_chainStyle和layout_constraintVertical_chainStyle分别对水平和垂直链设置模式,模式可选的值有:spread、packed、spread_inside
packed与layout_constraintHorizontal_weight一起使用:
ConstraintLayout为了解决嵌套问题还提供了一系列的辅助控件。
Guideline是一条参考线,可以帮助开发者进行辅助定位,并且实际上它并不会真正显示在布局中,Guideline可以用来做一些百分比分割之类的需求,Guideline有水平和垂直方向之分,位置可以使用针对父级的百分比或者针对父级位置的距离
android:orientation="horizontal|vertical" 辅助线的对齐方式
app:layout_constraintGuide_percent="0-1" 距离父级宽度或高度的百分比(小数形式)
app:layout_constraintGuide_begin="" 距离父级起始位置的距离(左侧或顶部)
app:layout_constraintGuide_end="" 距离父级结束位置的距离(右侧或底部)
下面代码中设置了一条水平方向位置在父级垂直方向0.3(30%)的Guideline,Text1的顶部依赖于Guideline,这样无论布局如何更改,Guideline的位置始终都会是父级垂直方向30%的位置。
Barrier不会出现在实际的布局中,它的作用是形成一个屏障、障碍。这里借助constraintlayout网站(https://constraintlayout.github.io/basics/barriers.html)来讲解Barrier。
左边的Text1和Text2;右边的Text3。Text3被限制在Text1的末尾。
然而,因为在不同的情况下,Text1中的文本可能比Text2中的文本长,或者Text2中的文本比Text1长:
Barriers的配置属性如下:
app:barrierDirection="top|bottom|left|right|start|end"
app:constraint_referenced_ids="id,id"
Barrier会自动位于较宽的那个Text后面,也就间接让Text3也位于了正确的位置。
Flow是用于构建链的新虚拟布局,当链用完时可以缠绕到下一行甚至屏幕的另一部分。当您在一个链中布置多个项目时,这很有用,但是您不确定容器在运行时的大小。您可以使用它来根据应用程序中的动态尺寸(例如旋转时的屏幕宽度)构建布局。Flow是一种虚拟布局。在ConstraintLayout中,虚拟布局(Virtual layouts)作为virtual view group的角色参与约束和布局中,但是它们并不会作为视图添加到视图层级结构中,而是仅仅引用其它视图来辅助它们在布局系统中完成各自的布局功能。
Flow的constraint_referenced_ids关联的控件是没有设置约束的,这一点和普通的链是不一样的,这种排列方式是Flow的默认方式none,我们可以使用app:flow_wrapMode=""属性来设置排列方式,并且我们还可以使用flow_horizontalGap和flow_verticalGap分别设置两个view在水平和垂直方向的间隔。
app:flow_wrapMode="none"
none为默认值,所有引用的view形成一条链,水平居中,超出屏幕两侧的view不可见。
chain将所引用的view形成一条链,超出部分会自动换行,同行的view 会平分宽度
aligned:将所引用的view形成一条链,但view会在同行同列。
当flow_wrapMode的值是chian或aligned时,我们还可以针对不同的链进行配置
app:flow_horizontalStyle="packed|spread|spread_inside" 所有水平链的配置
app:flow_verticalStyle="packed|spread|spread_inside" 所有垂直链的配置
app:flow_firstHorizontalStyle="packed|spread|spread_inside" 第一条水平链的配置,其他条不生效
app:flow_firstVerticalStyle="packed|spread|spread_inside" 第一条垂直链的配置,其他条不生效
app:flow_lastHorizontalStyle="packed|spread|spread_inside" 最后一条水平链的配置,其他条不生效
app:flow_lastVerticalStyle="packed|spread|spread_inside" 最后一条垂直链的配置,其他条不生效
app:flow_horizontalStyle="packed|spread|spread_inside" 所有水平链的配置
对于不同大小view的对齐方式,Flow也提供了相应的属性进行配置(flow_wrapMode="aligned"时,我试着没有效果)。
app:flow_verticalAlign="top|bottom|center|baseline"
app:flow_horizontalAlign="start|end|center"
app:flow_horizontalStyle="spread_inside"
app:flow_wrapMode="none"
app:flow_horizontalStyle="spread_inside"
app:flow_wrapMode="none"
app:flow_horizontalStyle="spread_inside"
app:flow_wrapMode="none"
app:flow_horizontalStyle="spread_inside"
app:flow_wrapMode="none"
当flow_wrapMode属性为aligned和chian时,通过flow_maxElementsWrap属性控制每行最大的子View数量。
app:flow_verticalAlign="baseline"
app:flow_horizontalStyle="spread_inside"
app:flow_wrapMode="chain"
Layer继承自ConstraintHelper,是一个约束助手,相对于Flow来说,Layer的使用较为简单,常用来增加背景,或者共同动画,图层 (Layer) 在布局期间会调整大小,其大小会根据其引用的所有视图进行调整,代码的先后顺序也会决定着它的位置,如果代码在所有引用view的最后面,那么它就会在所有view的最上面,反之则是最下面,在最上面的时候如果添加背景,就会把引用的view覆盖掉。
可以看到,当Layer的代码在所有引用view的上面时,效果是正常的,因为此时所有的view都在Layer的上面,下面是Layer代码在最后面时的情况:
Layer把view覆盖住了。
ImageFilterButton和ImageFilterView是两个控件,他们之间的关系就和ImageButton与ImageView是一样的,所以这里就只拿ImageFilterView来做讲解。从名字上来看,它们的定位是和过滤有关系的,它们的大致作用有两部分,一是可以用来做圆角图片,二是可以叠加图片资源进行混合过滤。
圆角图片
ImageFilterButton和ImageFilterView可以使用两个属性来设置图片资源的圆角,分别是roundPercent和round,roundPercent接受的值类型是0-1的小数,根据数值的大小会使图片在方形和圆形之间按比例过度,round=可以设置具体圆角的大小,我在使用的过程中发现我的AndroidStudio,没有这两个属性的代码提示,也没有预览效果,但是运行起来是有效果的。
ImageFilterButton和ImageFilterView不但可以使用src来设置图片资源,还可以使用altSrc来设置第二个图片资源,altSrc提供的资源将会和src提供的资源通过crossfade属性形成交叉淡化效果,默认情况下,crossfade=0,altSrc所引用的资源不可见,取值在0-1。
crossfade=0
crossfade=0.5
crossfade=1