ConstraintLayout基本使用及知识点讲解
常见的约束布局 ConstraintLayout 的实践使用场景:
- 场景1:固定比例视图
- 场景2:N等分布局
- 场景3:百分比对齐
- 场景4:角度布局
- 场景5:超长限制强制约束
- 场景6:多组件协同约束
- 场景7:容器约束下的边界约束
场景1:固定比例视图
考虑下面这个场景,组件宽度撑满屏幕,高度按「宽度x固定比例」计算。
这样的布局,在以往的布局方式下,都需要通过动态计算后修改高度来实现,但是通过 ConstraintLayout,则可以直接在 XML 中实现。
通过 layout_constraintDimensionRatio,可以很方便的实现比例视图的控制,同时,比例可以设置的很灵活,满足各种条件的需要。
场景2:N等分布局
常见的N等分布局,例如三等分布局,通常都需要进行动态计算,根据屏幕宽度,减去间距后得到每部分的宽度,再动态设置给每个元素,而通过ConstraintLayout,则可以直接实现这样的效果。
效果如下图所示:
这其中的间距,主要是通过layout_constraintWidth_percent
来设置在当前容器尺寸下所占百分比来进一步约束大小。
如果去掉这个属性,那么会直接等分父容器尺寸。
另外,还可以通过layout_constraintHorizontal_weight属性来控制类似LinearLayout的weight属性的效果,实现按权重进行分配。
场景3:百分比对齐
在ConstraintLayout中,虽然不能使用 -margin 的方式来完成传统布局中的一些错位的效果,但是可以借助Space来实现类似的功能,例如借助Space来实现左边TextView在右边TextView某一百分比(或者是dp)对齐的场景。
app:layout_constraintHorizontal_bias="0.2"
水平方向偏移量
由于ConstraintLayout不支持-Margin,所以很多场景下,我们都可以借助Space等辅助元素来实现中转,完成传统布局下通过-Margin实现的效果。
场景4:角度布局
通过角度的方式来对元素进行排列,在传统布局中,只能通过 FrameLayout,并通过动态计算的方式,将角度换算为边距的方式来布局,但通过ConstraintLayout,则变的非常简单。
- layout_constraintCircle:引用另一个控件的 id。
- layout_constraintCircleRadius:到另一个控件中心的距离。
- layout_constraintCircleAngle:控件的角度(顺时针,0 - 360 度)
场景5:超长限制强制约束
下面这个场景,最下面的TextView最大不会超过第一个TextView的宽度。
效果如下所示。
这时候就需要通过使用app:layout_constrainedWidth
来使其宽度约束强制生效。
再考虑下面这个场景:
当第二个TextView文字超长的时候,希望它截断,而不会影响左右的TextView。这个场景非常常用,在很多业务场景下都会使用到这样的功能,传统布局下,只能在布局时动态计算文字宽度来进行动态修改,但通过ConstraintLayout,则可以非常方便的实现。
场景6:多组件协同约束
下面这个场景,多个组件的宽度不定,需要取最大宽度的组件在布局中展示,例如下面这个例子。
Email和Password两个TextView的宽度可能因为文字的不一样而不同,需要他们整体取最大宽度后,与右边元素进行对齐,如下所示。
这时候,就需要使用Barrier。Barrier 是用多个 View 作为限制源来决定自身位置的一种辅助线.,Barrier和Group一样,通过constraint_referenced_ids来组合需要作用的组件,代码如下。
其中app:barrierDirection
设置为right,即右侧不超过Barrier,再让剩余组件与Barrier进行约束即可。
场景7:容器约束下的边界约束
面这个场景,中间的TextView被约束在两边的组件中,如下所示。
在个例子的重点是将layout_width设置为0dp,即MATCH_CONSTRAINT,即可实现这样的效果。
下面进一步思考下这个场景。
当TextView文字较少时,可以发现其尺寸是默认占据了整个约束空间,这时候,如果要求TextView只显示文字大小,类似设置wrap_content的效果,但是在文字长的时候,又必须被边缘约束,所以又不能设置wrap_content,这种场景下,可以通过layout_constraintWidth_default属性来解决,它提供了边缘约束下默认的尺寸设置方式。
前面说的类似wrap_content的效果,就可以使用wrap来设置。
app:layout_constraintWidth_default="wrap"
当然,不设置这个属性,将TextView的宽度设置为wrap_content,也是可以实现这个效果的,这就需要使用到前面讲的constrainedWidth属性了。
layout_constraintWidth_default
的默认值为spread,即占据边缘约束下的所有空间。