ConstraintLayout:如何将一个视图置于另一个视图的中心并保持在父边界内?

ConstraintLayout: how to center a view under another and also stay within parent bounds?

我想将视图置于电子邮件下方的另一个像这样的 "sign out" 按钮下方:

我通过使用 ConstraintLayout 作为父级并将底视图的左右边缘限制为顶视图的左右边缘来做到这一点。这正确地将两个视图居中。 (请注意,我不想将父视图居中。)

我遇到的问题是,如果顶视图很窄,底视图最终可能会 运行 位于父视图的右侧,如此处(来自布局编辑器):

我事先不知道 运行 时顶视图会缩小到什么程度。 (不一定是电子邮件地址,即使是,我认识的人的电子邮件地址只有 8 个字符!)

我想设置约束,使底视图在顶视图下方居中,但如果它靠右太远,它会向左移动刚好足以避免越过准则。顶视图的右边缘需要保持固定。我怎样才能达到这种效果? (我不拘泥于使用 ConstraintLayout,如果有其他更好的方法的话。)

这是我正在使用的实际布局文件:

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

    <TextView
        android:id="@+id/user_name"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginEnd="10dp"
        android:layout_marginTop="10dp"
        android:text="user"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:ignore="HardcodedText"
        tools:layout_constraintRight_creator="1"
        tools:layout_constraintTop_creator="1"/>

    <View
        android:id="@+id/scrim"
        android:layout_width="0dp"
        android:layout_height="0dp"
        android:background="@android:color/transparent"
        android:visibility="gone"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        tools:layout_constraintLeft_creator="1"
        tools:layout_constraintTop_creator="1"
        tools:visibility="visible"/>

    <Button
        android:id="@+id/sign_out"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="10dp"
        android:background="@android:drawable/dialog_holo_light_frame"
        android:text="@string/sign_out"
        android:visibility="gone"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@id/user_name"
        tools:visibility="visible"/>

</android.support.constraint.ConstraintLayout>

I didn't get you perfectly, but I'm posting the answer for what I understood.

<?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:layout_width="match_parent"
    android:layout_height="match_parent">

<TextView
    android:id="@+id/user_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="20dp"
    android:layout_marginRight="20dp"
    android:text="user"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="HardcodedText"
    tools:layout_constraintRight_creator="1"
    tools:layout_constraintTop_creator="1" />

<Button
    android:id="@+id/sign_out"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="10dp"
    android:background="@android:drawable/dialog_holo_light_frame"
    android:text="SIGNOUT"
    android:visibility="gone"
    app:layout_constraintTop_toBottomOf="@id/user_name"
    tools:visibility="visible"
    app:layout_constraintLeft_toLeftOf="@+id/user_name"
    app:layout_constraintRight_toRightOf="@+id/user_name" />

在我看来,ConstraintLayout 不是完成这项工作的最佳工具。您可能仍会使用 ConstraintLayout 作为您的顶级视图,但要获得您想要的,我相信您必须将 TextViewButton 嵌套在 LinearLayout 中。

问题的核心是你希望哪个视图更宽接触父级的边缘,哪个视图更小以相对于更宽的视图水平居中。鉴于 ConstraintLayout 不允许您对给定视图的边缘执行多个约束,因此它无法执行此操作。

但是,

带有 android:gravity="center_horizontal" 的垂直 LinearLayout 应该完全符合您的要求。然后你可以把它放在屏幕的右上角(可以使用 ConstraintLayout,或者其他方式)。

编辑

重新阅读您的问题后,我意识到我误解了您的要求。您需要 TextView 始终位于右上角,并且 Button 在文本视图下方居中,除非这会导致它被父级的边缘剪裁。

我仍然认为 LinearLayout 是前往此处的方式,但您需要对它的子项更加复杂一些。这应该有效:

<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">

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        constrants=top-right>

        <TextView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="end"/>

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_horizontal"/>

    </LinearLayout>

</ConstraintLayout>

我觉得可以试试

<?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:layout_width="match_parent"
android:layout_height="match_parent">

<TextView
    android:id="@+id/user_name"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginEnd="10dp"
    android:layout_marginTop="10dp"
    android:text="user@mail.com"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    tools:ignore="HardcodedText"
    tools:layout_constraintRight_creator="1"
    tools:layout_constraintTop_creator="1"/>

<View
    android:id="@+id/scrim"
    android:layout_width="0dp"
    android:layout_height="0dp"
    android:background="@android:color/transparent"


    android:layout_marginTop="8dp"
    app:layout_constraintBottom_toBottomOf="parent"
    android:layout_marginBottom="8dp"
    app:layout_constraintVertical_bias="0.0"
    android:layout_marginRight="8dp"
    app:layout_constraintRight_toRightOf="parent"
    android:layout_marginLeft="8dp"
    app:layout_constraintLeft_toLeftOf="parent"
    app:layout_constraintTop_toBottomOf="@+id/sign_out"
    app:layout_constraintHorizontal_bias="0.0" />

<Button
    android:id="@+id/sign_out"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_marginTop="11dp"
    android:background="@android:drawable/dialog_holo_light_frame"
    android:text="sign_out"
    android:visibility="gone"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintRight_toRightOf="parent"
    app:layout_constraintTop_toBottomOf="@id/user_name"
    tools:visibility="visible"
    android:layout_marginRight="11dp" />

</android.support.constraint.ConstraintLayout>

假设有2个视图。

  • Select 第一次观看
  • shift
  • Select 第二个视图
  • 右击
  • Select 对齐 >> 水平居中.

完成。