如何在 Android 约束布局中支持水平位置的 3 个视图的wrap_content和match_parent条件



我想创建一个复合视图,其中包含 3 个水平位置的视图。当我将此复合视图的宽度设置为 WRAP_CONTENT 时,我希望所有这 3 个视图并排定位,因为它是WRAP_CONTENT。但是当我将宽度设置为 MATCH_PARENT 时,我希望第二个视图占据屏幕的整个空间(但第二个视图仍然位于第一个视图旁边)。

例:

WRAP_CONTENT:

|视图1 视图2 视图3 --空白空间--|

MATCH_PARENT:

|视图1 视图2 --空白空间-- 视图3|

由于某种原因,我必须在此处使用约束布局。

我已经尝试了下面的代码。当我尝试将第二个视图的宽度更改为WRAP_CONTENT,并将整个约束布局设置为 MATCH_PARENT 时,第二个视图位于中心(而我想要的是将位置保持在左侧)

<androidx.constraintlayout.widget.ConstraintLayout
android:layout_width="match_parent"
android:layout_height="wrap_content">
<TextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
android:text="view1"/>
<TextView
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/test1"
app:layout_constraintEnd_toStartOf="@id/test3"
android:text="view2"/>
<TextView
android:id="@+id/view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="view3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

谢谢。我很欣赏任何解决方案。

我不是 100% 确定我理解您要完成的任务,但我会为我能想象的每种情况扩展(已经给出答案):

| V1 | V2 | V3 ...... |,您只需告诉第 3 个视图与android:layout_width="0dp"match_constraints,它将占用其他视图(已换行)留下的所有空间。

这将产生我从这里理解的相同输出:

|view1 view2 view3 --empty-space--|

除非你的意思是-- empty space --|V1|V2|V3| ..... |在这种情况下,你需要一个约束布局Chainbias

在最左侧的视图中,添加:

app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"

并确保所有视图之间都有连接,就像 view1(最左边)一样:startToStart=parent,endToStart=view2。然后,View2 将具有 startToEnd=view1、endToStart=view3 和 view3...开始到结束=视图2, 结束到结束=父级

你明白了。

这会将所有视图打包到start最后留下空白空间。无论父项的约束(匹配/换行)如何,上述方法都可以工作,因为引擎无论如何都会根据可用空间来定位/调整视图大小。

现在,对于您的MATCH_PARENT示例:

|view1 view2 --empty-space-- view3|

不清楚(对我来说)你所说的--空白是什么意思--,这是否意味着您希望view2包装其内容? 还是您希望 View2 使用所有可用空间并将 View3 推送到最后?

我假设你的意思是所有视图都在换行并且有空白空间。如果您不知道确切的尺寸,那么关于如何实现这一目标有一个很好的答案(提示,您需要在两者之间链接一个空格),因为引擎将无法确定每个视图在计算大小和包装它们之前将占用多少空间。

现在,如果您不介意 view2 占用所有剩余空间并破坏链(仅在需要时),您可以执行正常的偏置链,但使用默认的扩展条件进行包装:

所以它看起来像这样:

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/view2"
app:layout_constraintTop_toTopOf="parent"
android:text="view1"/>
<TextView
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/view1"
app:layout_constraintEnd_toStartOf="@id/view3"
app:layout_constraintWidth_default="spread"
android:text="view2"/>
<TextView
android:id="@+id/view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/view2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="1.0"
android:text="view3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

这将产生类似以下内容:

| V1 | V2.............|V3|

这可能对你有用,也可能对你不起作用。

ConstraintLayout 提供了确定子视图之间的链的功能。有包装,spread_inside和涂抹。

您可以在此处阅读有关链接的信息: https://constraintlayout.com/basics/create_chains.html

Views放在一个有0偏差的水平链中,将它们向左对齐。

打包链会将Views并排分组在父ConstraintLayout的中间。当Views的宽度均未设置为0dp(匹配约束)时,您可以通过设置偏差来控制此组的水平定位。如果将第二个View设置为0dp,则将占用所有剩余空间。

您可以在文档中阅读有关链的更多信息。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/view2"
app:layout_constraintTop_toTopOf="parent"
android:text="view1"/>
<TextView
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/view1"
app:layout_constraintEnd_toStartOf="@id/view3"
android:text="view2"/>
<TextView
android:id="@+id/view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/view2"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="view3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

编辑:

我能想到两种选择。

首先,在将父布局的宽度设置为wrap_content的同时,您还可以将第二个View的宽度设置为wrap_content

第二个选项是在第二个和第三个View之间添加一个Space,以便在父布局设置为match_constraint时填充剩余空间,或者在将其设置为wrap_content时缩小。

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/view1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintHorizontal_bias="0"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintEnd_toStartOf="@id/view2"
app:layout_constraintTop_toTopOf="parent"
android:text="view1"/>
<TextView
android:id="@+id/view2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintStart_toEndOf="@id/view1"
app:layout_constraintEnd_toStartOf="@id/space"
android:text="view2"/>
<Space
android:id="@+id/space"
android:layout_width="0dp"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/view2"
app:layout_constraintEnd_toStartOf="@id/view3"
app:layout_constraintTop_toTopOf="parent"/>
<TextView
android:id="@+id/view3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintStart_toEndOf="@id/space"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintEnd_toEndOf="parent"
android:text="view3"/>
</androidx.constraintlayout.widget.ConstraintLayout>

将其添加到 A 视图中

app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"

并将 B 设置为 A 的从属:

前任:

<TextView
android:id="@+id/tv_description"
android:layout_width="0dp"
...
app:layout_constraintHorizontal_bias="0.0"
app:layout_constraintHorizontal_chainStyle="packed"
app:layout_constraintEnd_toStartOf="@+id/btn_allow_permission"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_permission_title" />
<Button
app:layout_constraintStart_toEndOf="@+id/tv_description"
...
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintTop_toTopOf="parent" />

最新更新