ConstraintLayout核心用法详解(三):引导线、屏障、组和占位
整理旧电脑上的一些笔记【前言】ConstraintLayout核心用法详解一相对定位、边距、偏移与环形定位ConstraintLayout核心用法详解二尺寸约束与链约束今天继续整理ConstraintLayout。ConstraintLayout的特点扁平布局无嵌套一个层级就可以绘制复杂布局渲染性能高集合了线性布局、相对布局、百分比布局的特点和大多数功能支持可视化环境下拖拽绘制约束布局轻松地为应用中使用的 UI 组件添加动画效果。1. 引导线约束GuidelineAPP 开发过程中经常遇到一个场景就是为了保证控件和设计图对齐会手动绘制一条或多条其他颜色的水平竖直线来方便统一边界。而ConstraintLayout中的Guideline引导线辅助线同样具有相同功能但用户看不到该线。Guideline设计出来仅用于布局目的而且它仅可以在ConstraintLayout布局内生效。Guideline分为水平和垂直两种支持三种定位方式layout_constraintGuide_begin指定引导线距父布局左侧或顶部的固定距离layout_constraintGuide_end指定引导线距父布局右侧或底部的固定距离layout_constraintGuide_percent指定引导线距父布局宽度或高度的百分比位置。androidx.constraintlayout.widget.ConstraintLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroidx.constraintlayout.widget.Guidelineandroid:idid/guideline_verandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationverticalapp:layout_constraintGuide_begin100dp/androidx.constraintlayout.widget.Guidelineandroid:idid/guideline_horandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationhorizontalapp:layout_constraintGuide_begin100dp/androidx.constraintlayout.widget.Guidelineandroid:idid/guideline_percentandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationhorizontalapp:layout_constraintGuide_percent0.5//androidx.constraintlayout.widget.ConstraintLayout预览图如下控件可以通过约束关系绑定Guideline如下面代码所示androidx.constraintlayout.widget.ConstraintLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentandroidx.constraintlayout.widget.Guidelineandroid:idid/guideline_verandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationverticalapp:layout_constraintGuide_begin100dp/androidx.constraintlayout.widget.Guidelineandroid:idid/guideline_horandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationhorizontalapp:layout_constraintGuide_begin100dp/androidx.constraintlayout.widget.Guidelineandroid:idid/guideline_percentandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:orientationhorizontalapp:layout_constraintGuide_percent0.5/Buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginStart10dpandroid:textAapp:layout_constraintStart_toStartOfid/guideline_verapp:layout_constraintTop_toTopOfparent/Buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginEnd10dpandroid:textBapp:layout_constraintEnd_toEndOfparentapp:layout_constraintTop_toBottomOfid/guideline_hor/Buttonandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginEnd10dpandroid:textCapp:layout_constraintBottom_toTopOfid/guideline_percentapp:layout_constraintStart_toEndOfid/guideline_ver//androidx.constraintlayout.widget.ConstraintLayout预览图如下2.屏障约束BarrierBarrier和Guideline一样都是不可见都是用来帮助定位的控件。但在使用场景上不一样。比如有下面这样一种布局有三个TextViewTextView_1显示Hello ConstraintLayoutTextView_2显示Hello BarrierTextView_3显示多条Hello ConstraintLayout,Hello ConstraintLayout…。很明显 TextView_1 中显示的内容宽度比 TexView_2 中内容宽度大TextView_3 和 TextView_1 有约束(layout_constraintStart_toEndOf“id/tv_1”)当前界面三个TextView显示都是正常的但是当我们点击按钮【改变文字内容】就会出现下面视频中的问题。TextView_1文字内容变少TextView_3遮挡了TextView_2。如何解决我们可以使用LinearLayout把 TextView_1 和 TextView_2 作为子 view然后让TextView_3 和LinearLayout有约束。但是这意味着我们增加了新的层级布局。这不是我们希望的这种时候就是Barrier大显身手的时候了。Barrier属性包括barrierDirection“start|end|top|bottom|left|right”必选属性设置barrier相对于viewreferenced_ids设置的的位置(屏障的方向)constraint_referenced_ids“id1,id2,id3…”必选属性view的idbarrierAllowsGoneWidgets“true|false”可选属性是否包含GONE状态下的ViewbarrierMargin“具体值”设置barrier外边距。仅看文字可能不好理解我们直接看代码演示androidx.constraintlayout.widget.ConstraintLayoutxmlns:androidhttp://schemas.android.com/apk/res/androidxmlns:apphttp://schemas.android.com/apk/res-autoandroid:layout_widthmatch_parentandroid:layout_heightmatch_parentTextViewandroid:idid/tv_1android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textHello ConstraintLayoutapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent/TextViewandroid:idid/tv_2android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:textHello Barrierandroid:textColor#8E24AAapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/tv_1/androidx.constraintlayout.widget.Barrierandroid:idid/barrierandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentapp:barrierAllowsGoneWidgetstrueapp:barrierDirectionendapp:barrierMargin10dpapp:constraint_referenced_idstv_1,tv_2/TextViewandroid:idid/tv_3android:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:layout_marginStart10dpandroid:textHello Constraint,Hello ConstraintLayout,Hello ConstraintLayout,Hello Constraint,Hello ConstraintLayout,Hello ConstraintLayoutandroid:textColor#D81B60app:layout_constraintStart_toEndOfid/barrierapp:layout_constraintTop_toTopOfparent/Buttonandroid:idid/btn_changeandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text点击改变文字内容app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparent//androidx.constraintlayout.widget.ConstraintLayout示例中 barrierDirection“end”、constraint_referenced_ids“tv_1,tv_2”代表的就是我们把 barrier设置到 tv_1 和 tv_2 两个 View 的 end 位置如果改为 start就代表把 barrier 设置到 tv_1 和 tv_2两个 View 的开始位置即 barrier 紧贴屏幕左侧。使用Barrier效果3. 组GroupConstraintLayout没有层级嵌套大大提高了UI性能和减少卡顿但是也带了一个新的使用问题。在LinearLayout或RelativeLayout布局中当我们需要让多个 View 隐藏时候我们可以直接隐藏父布局。ConstraintLayout下则需要针对每个 view 进行setVisible(View.INVISIBLE|View.VISIBLE)如此简单又多见的场景Android 不可能没有想到——Group正是用来解决这个问题的。This class controls the visibility of a set of referenced widgets. Widgets are referenced by being added to a comma separated list of ids, The visibility of the group will be applied to the referenced widgets. It’s a convenient way to easily hide/show a set of widgets without having to maintain this set programmatically.Group被用来控制一组被引用控件的可见性将控件ID添加到以逗号分隔的列表中。代码如下ImageViewandroid:idid/iv_loadingandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:srcdrawable/icon_loadingapp:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent/TextViewandroid:idid/tv_loadingandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text正在加载...app:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toBottomOfid/iv_loading/androidx.constraintlayout.widget.Groupandroid:idid/group_loadingandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:visibilityvisibleapp:constraint_referenced_idsiv_loading,tv_loading/当想要将ImageView和TextView都隐藏时我们可以这样写valgroupfindViewByIdGroup(R.id.group_loading)valbtnfindViewByIdButton(R.id.btn_1)btn.setOnClickListener{if(group.visibilityView.VISIBLE){group.visibilityView.INVISIBLE}else{group.visibilityView.VISIBLE}}//没有Group的话,需要将每个View设置可见、不可见loadingImg.visibilityView.INVISIBLE loadingTxt.visibilityView.INVISIBLE4. 占位符PlaceholderConstraintLayout还提供一个新的控件叫Placeholder它是一个空的可定位的占位区域很好的解决了某些场景下布局动态改变和复用问题。APlaceholderprovides a virtual object which can position an existing object.Placeholder的核心概念虚拟定位Placeholder本身不显示任何内容仅在布局中占据位置内容替换Placeholder提供方法setContent(viewId)viewId是新视图IDPlaceholder占据的位置就会显示传入的viewId位置迁移旧位置的viewId会消失(GONE)。Placeholder可以在XML布局中使用属性app:content“view_id”来直接指定视图也可以使用方法setContentId(view_id)在运行的Kotlin/Java代码中动态更改。ImageViewandroid:idid/iv_androidandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:srcmipmap/ic_launcherapp:layout_constraintStart_toStartOfparentapp:layout_constraintTop_toTopOfparent/androidx.constraintlayout.widget.Placeholderandroid:idid/placeholderandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentapp:contentid/iv_androidapp:layout_constraintEnd_toEndOfparentapp:layout_constraintTop_toTopOfparent/Buttonandroid:idid/btn_changeandroid:layout_widthwrap_contentandroid:layout_heightwrap_contentandroid:text切换内容app:layout_constraintBottom_toBottomOfparentapp:layout_constraintEnd_toEndOfparentapp:layout_constraintStart_toStartOfparent/在Kotlin代码中动态改变valimagefindViewByIdImageView(R.id.iv_android)valplaceholderfindViewByIdPlaceholder(R.id.placeholder)valbtnfindViewByIdButton(R.id.btn_change)btn.setOnClickListener{placeholder.setContentId(R.id.iv_android)}5. 参考资料ConstraintLayout Developershttps://developer.android.google.cn/develop/ui/views/layout/constraint-layout?hlzh_cnGitHub资料https://github.com/android/views-widgets-samples/tree/main/ConstraintLayoutExamplesGrouphttps://developer.android.google.cn/reference/androidx/constraintlayout/widget/Group?hlenPlaceholderhttps://developer.android.google.cn/reference/kotlin/androidx/constraintlayout/widget/Placeholder?hlen