ConstraintLayout之Barrier

本文详细介绍ConstraintLayout中的Barrier特性,该特性能帮助解决多语言环境下布局错位问题,通过创建虚拟视图来动态调整布局,提高应用的适配性和美观度。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

泡在网上的日子 / 文 发表于2017-10-17 11:41 第5945次阅读 ConstraintLayout,转载网址http://www.jcodecraeer.com/a/anzhuokaifa/androidkaifa/2017/1017/8601.html

ConstraintLayout 的Barrier是1.1版本引入的一个非常实用的功能,但是官网没有对它做任何介绍,只提了一下名字:https://androidstudio.googleblog.com/2017/05/constraintlayout-110-beta-1-release.html 。

更正:官网还对Barrier这个类做了一些介绍:https://developer.android.com/reference/android/support/constraint/Barrier.html

它跟 Guideline  一样属于Virtual Helper objects,在运行时的界面上看不到,但是要比Guideline实用多了。

constraintlayout网站(非官方)对它的介绍已经非常清晰了:https://constraintlayout.github.io/basics/barriers.html 

下面是翻译:

当我们创建布局的时候,有时会遇到布局会随着本地化变化的情况,下面是一个简单的例子:

barriers_alignment_en.png

我们有三个TextViews: 左边 textView1 和 textView2 ,右边 textView3。textView3 约束在 textView1 的右边,效果也符合我们的预期。

但是当需要支持多语言的时候事情就变得复杂了。如果我们添加德语就出现了问题,因为在英语里面textView1的文字是长于textView2的,但是在德语中却是textView2的文字比textView1长:

barriers_alignment_de.png

这里的问题在于textView3仍然是相对于textView1的,所以textView2直接插入了textView3中。在设计视图里看起来更明显(白色背景的那个)。

比较直接的解决办法是使用TableLayout,或者把 textView1 & textView2 包裹在一个垂直的,android:layout_width="wrap_content" 的 LinearLayout中。然后让textView3约束在这个LinearLayout的后面。但是我们有更好的办法:Barriers。

Barrier 是一个虚拟视图,类似于 Guideline,用来约束对象。Barrier 和 Guideline 的区别在于它是由多个 view 的大小决定的。在这个例子中,我们不知道 textView1 和 textView2 哪个长些,因此我们可以 基于这两个 view 的宽度创建一个Barrier。我们可以让 textView3 约束在 Barrier 后面。

在编辑器中创建Barriers

首先选择上下文菜单的create a vertical barrier,创建一个垂直的barrier:

注:Android Studio2.3貌似没有这个菜单,Android Studio3.0有,但是在help菜单组的下级菜单,跟下面的演示图有些区别。

barrier_create.gif

你可以在组建树(component tree)中看到Barrier(左边靠近底部的面板)。

我们可以通过拖动改变它的位置(可选项):

barrier_order.gif

接下来我们需要设置Barrier 方向(direction)。这里我们是想让Barrier根据textView1 和 textView2 的大小确定是在谁的后面,因此我们需要把 direction 设置为 end:

barrier_direction.gif

最后一步是告诉Barrier它是相对于哪些view。我不用约束来形容是因为约束一般指一对一的,而这里是多个view。我们需要为 Barrier 指定引用的view的 ID , 可以通过在 component tree 中把view拖动到 Barrier 来完成:

barrier_references.gif

一旦定义好之后,这些引用将被列为 Barrier 的 children。而且你还会在蓝色面板中看到Barrier跳到了新的位置(垂直的虚线)。

现在 Barrier 就已经定义好了,只剩下把textView3的约束从相对于 textView1 改为 相对于 Barrier 了:

barrier_constrain.gif

完了之后 textView3 就到了 textView2 的后面了。

为了看到整体的效果,可以切换语言,此时你会看到 Barrier 会自动位于较宽的那个 textView 后面,也就间接让 textView3 也位于了正确的位置:

barrier_example.gif

在XML中创建Barriers

XML代码其实也非常简单:

 
  1. <?xml version="1.0" encoding="utf-8"?>
  2. <android.support.constraint.ConstraintLayout 
  3.   xmlns:android="http://schemas.android.com/apk/res/android"
  4.   xmlns:app="http://schemas.android.com/apk/res-auto"
  5.   android:layout_width="match_parent"
  6.   android:layout_height="match_parent">
  7.  
  8.   <TextView
  9.     android:id="@+id/textView1"
  10.     android:layout_width="wrap_content"
  11.     android:layout_height="wrap_content"
  12.     android:layout_marginStart="16dp"
  13.     android:layout_marginTop="16dp"
  14.     android:text="@string/warehouse"
  15.     app:layout_constraintStart_toStartOf="parent"
  16.     app:layout_constraintTop_toTopOf="parent" />
  17.  
  18.   <TextView
  19.     android:id="@+id/textView2"
  20.     android:layout_width="wrap_content"
  21.     android:layout_height="wrap_content"
  22.     android:layout_marginStart="16dp"
  23.     android:layout_marginTop="8dp"
  24.     android:text="@string/hospital"
  25.     app:layout_constraintStart_toStartOf="parent"
  26.     app:layout_constraintTop_toBottomOf="@+id/textView1" />
  27.  
  28.   <android.support.constraint.Barrier
  29.     android:id="@+id/barrier7"
  30.     android:layout_width="wrap_content"
  31.     android:layout_height="wrap_content"
  32.     app:barrierDirection="end"
  33.     app:constraint_referenced_ids="textView2,textView1" />
  34.  
  35.   <TextView
  36.     android:id="@+id/textView3"
  37.     android:layout_width="0dp"
  38.     android:layout_height="wrap_content"
  39.     android:layout_marginStart="8dp"
  40.     android:text="@string/lorem_ipsum"
  41.     app:layout_constraintStart_toEndOf="@+id/barrier7"
  42.     app:layout_constraintTop_toTopOf="parent" />
  43.  
  44. </android.support.constraint.ConstraintLayout>

Barrier特别的地方就在于Barrier元素自身。app:barrierDirection 属性决定 Barrier 的方向 - 这里把它放在被引用view的后面。被引用的view 是布局中的view的id列表,用逗号隔开。

### Android ConstraintLayout 使用教程 #### 一、简介 ConstraintLayout 是一种强大的布局容器,允许开发者通过定义视图之间的相对位置关系来构建复杂的用户界面。这种布局方式可以减少嵌套层级,提高应用性能并简化XML文件结构[^1]。 #### 二、基本概念 - **约束(Constraints)**: 每个子View都需要至少两个水平方向上的约束和两个垂直方向上的约束才能被固定住。 - **链表(Chains)**: 可以把多个view连接成一条线,在这条线上它们会均匀分布或者按照权重分配空间。 - **屏障(Guideline & Barrier)**: Guideline用于设置固定的百分比或dp距离;Barrier则是动态计算一组views边缘的最大值作为自己的边界[^2]。 #### 三、简单示例 下面展示如何创建一个简单的登录页面: ```xml <?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"> <!-- 用户名输入框 --> <EditText android:id="@+id/editTextUsername" android:hint="用户名" android:inputType="textEmailAddress" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <!-- 密码输入框 --> <EditText android:id="@+id/editTextPassword" android:hint="密码" android:inputType="textPassword" android:layout_marginTop="16dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/editTextUsername" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> <!-- 登录按钮 --> <Button android:text="登录" android:layout_marginTop="16dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintTop_toBottomOf="@id/editTextPassword" app:layout_constraintStart_toStartOf="parent" app:layout_constraintEnd_toEndOf="parent"/> </androidx.constraintlayout.widget.ConstraintLayout> ``` 上述代码片段展示了三个主要组件——`EditText`(分别代表用户名和密码字段) 和 `Button`(表示提交按钮),并通过一系列属性设置了这些控件相对于父级Container的位置关系[^3]。 #### 四、高级特性 除了基础的功能外, 还支持更灵活的设计模式比如比例尺寸调整、旋转角度设定等特殊效果的应用场景下非常有用处。同时配合可视化编辑工具能够极大提升工作效率。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值