垂直限制多个视图以永不越线?

Constrain many views vertically to never cross a line?

我有一个包含许多输入的注册表单,每个输入的边距为 8dp。它还有一个标题,marginBottom 为 24dp。在某些情况下,有些输入必须隐藏。

所以我希望第一个,无论它是什么,与标题有特定的 24dp 边距,并且彼此之间有 8dp 的边距。

我想用ConstraintLayout解决这个问题。这是我的 xml:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:id="@+id/cho_card_document"
tools:background="#FF0000"
tools:ignore="SpUsage, RtlHardcoded,RtlSymmetry"
android:layout_width="match_parent"
android:layout_height="match_parent">

<View
    android:layout_width="274dp"
    android:layout_height="200dp"
    android:background="@drawable/cho_shape_round_white_background"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:layout_marginTop="50dp"
    android:id="@+id/cho_ticket_view"/>

<TextView
    android:layout_height="wrap_content"
    android:layout_width="0dp"
    android:id="@+id/title"
    tools:text="Awesome Title Form"
    android:layout_marginTop="24dp"
    android:layout_marginLeft="16dp"
    app:layout_constraintRight_toRightOf="@+id/cho_ticket_view"
    app:layout_constraintLeft_toLeftOf="@+id/cho_ticket_view"
    app:layout_constraintTop_toTopOf="@+id/cho_ticket_view" />

<TextView
    android:layout_height="wrap_content"
    android:layout_width="0dp"
    android:id="@+id/input1"
    tools:text="Awesome Input 1"
    android:layout_marginTop="24dp"
    app:layout_constraintLeft_toLeftOf="@+id/title"
    app:layout_constraintTop_toBottomOf="@+id/title" />

<TextView
    android:layout_height="wrap_content"
    android:layout_width="0dp"
    android:id="@+id/input2"
    tools:text="Awesome Input 2"
    android:layout_marginTop="8dp"
    app:layout_constraintLeft_toLeftOf="@+id/title"
    app:layout_constraintTop_toBottomOf="@+id/input1" />

<TextView
    android:layout_height="wrap_content"
    android:layout_width="0dp"
    android:id="@+id/input3"
    tools:text="Awesome Input 3"
    android:layout_marginTop="8dp"
    app:layout_constraintLeft_toLeftOf="@+id/title"
    app:layout_constraintTop_toBottomOf="@+id/input2" />

</android.support.constraint.ConstraintLayout>

编辑:我已经用实际实现和一些屏幕截图更新了布局。

之前:

隐藏 input1 后,我 input2title

太近了

最佳解决方案是将它们放在一个 Contraintlayout 中。然后将该布局限制在标题表单底部所需的边距处。那么当你隐藏input 1时,input 2最多只能向上移动并替换input 1的位置,但不会移动整体布局。希望这有帮助

    <RelativeLayout
        android:layout_margin="24dp"
        android:id="@+id/title1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">
    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/title"
        android:text="Awesome Title Form"
       />
</RelativeLayout>
    <RelativeLayout
        android:layout_margin="8dp"
        android:layout_below="@+id/title1"
        android:id="@+id/subject"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content">


    <TextView
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/input1"
        android:text="Awesome Input 1"
    />

    <TextView
        android:layout_below="@+id/input1"
        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/input2"
        android:text="Awesome Input 2"
   />

    <TextView
        android:layout_below="@+id/input2"

        android:layout_height="wrap_content"
        android:layout_width="wrap_content"
        android:id="@+id/input3"
        android:text="Awesome Input 3"

 />
    </RelativeLayout>

你可以通过做两件事来解决这个问题:

  • 重新平衡垂直边距的分配方式
  • 在您的标题和三个输入视图之间创建垂直 "chain"

重新平衡利润很容易。将 input1 视图上的 android:layout_marginTop="24dp" 更改为使用 8dp(就像 input2input3),并将 android:layout_marginBottom="16dp" 添加到 title 视图。这样,无论您输入的哪个视图是 hidden/visible,标题和第一个输入之间的总间距将始终为 24dp。

创建链有点复杂。链中的每个视图都必须同时具有顶部和底部约束。链中的第一个视图应将其顶部约束为 cho_ticket_view,链中的最后一个视图应将其底部约束为 cho_ticket_view,其他所有视图(在两个方向上)应约束为它的邻居。

这是它的样子(为简洁起见省略了其他属性):

<TextView
    android:id="@+id/title"
    app:layout_constraintTop_toTopOf="@+id/cho_ticket_view"
    app:layout_constraintBottom_toTopOf="@+id/input1"/>

<TextView
    android:id="@+id/input1"
    app:layout_constraintTop_toBottomOf="@+id/title"
    app:layout_constraintBottom_toTopOf="@+id/input2"/>

<TextView
    android:id="@+id/input2"
    app:layout_constraintTop_toBottomOf="@+id/input1"
    app:layout_constraintBottom_toTopOf="@+id/input3"/>

<TextView
    android:id="@+id/input3"
    app:layout_constraintTop_toBottomOf="@+id/input2"
    app:layout_constraintBottom_toBottomOf="@+id/cho_ticket_view"/>

设置好这八个约束后,这四个视图现在就是一个 "chain"。可以通过向链的 "head" 添加额外的属性来配置链(第一个视图,即 title 给你)。

您将需要 title 视图中的这些属性:

    app:layout_constraintVertical_chainStyle="packed"
    app:layout_constraintVertical_bias="0"

使链成为 "packed" 链意味着它将所有额外的 space 放在链外(而不是链中的视图之间)。给它一个 0 的垂直偏差意味着所有额外的 space 都在链的下方(而不是上方)。

这是完整的 XML,结合了上述所有内容:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/cho_card_document"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:background="#FF0000"
    tools:ignore="SpUsage, RtlHardcoded,RtlSymmetry">

    <View
        android:id="@+id/cho_ticket_view"
        android:layout_width="274dp"
        android:layout_height="200dp"
        android:layout_marginTop="50dp"
        android:background="@drawable/cho_shape_round_white_background"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>

    <TextView
        android:id="@+id/title"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="24dp"
        android:layout_marginLeft="16dp"
        android:layout_marginBottom="16dp"
        app:layout_constraintTop_toTopOf="@+id/cho_ticket_view"
        app:layout_constraintLeft_toLeftOf="@+id/cho_ticket_view"
        app:layout_constraintRight_toRightOf="@+id/cho_ticket_view"
        app:layout_constraintBottom_toTopOf="@+id/input1"
        app:layout_constraintVertical_chainStyle="packed"
        app:layout_constraintVertical_bias="0"
        tools:text="Awesome Title Form"/>

    <TextView
        android:id="@+id/input1"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/title"
        app:layout_constraintLeft_toLeftOf="@+id/title"
        app:layout_constraintBottom_toTopOf="@+id/input2"
        tools:text="Awesome Input 1"/>

    <TextView
        android:id="@+id/input2"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/input1"
        app:layout_constraintLeft_toLeftOf="@+id/title"
        app:layout_constraintBottom_toTopOf="@+id/input3"
        tools:text="Awesome Input 2"/>

    <TextView
        android:id="@+id/input3"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginTop="8dp"
        app:layout_constraintTop_toBottomOf="@+id/input2"
        app:layout_constraintLeft_toLeftOf="@+id/title"
        app:layout_constraintBottom_toBottomOf="@+id/cho_ticket_view"
        tools:text="Awesome Input 3"/>

</android.support.constraint.ConstraintLayout>