【问题标题】:ConstraintLayout: how to center a view under another and also stay within parent bounds?ConstraintLayout:如何在另一个视图下居中并保持在父边界内?
【发布时间】:2017-07-27 03:27:50
【问题描述】:

我想在电子邮件下方的另一个类似“退出”按钮下的视图居中:

我通过使用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>

【问题讨论】:

  • @Enzokie - 不幸的是,这将允许顶视图的后沿向左移动。我目前的选择是消除底视图开始和顶视图开始之间的约束。这牺牲了居中(这是一个问题),但解决了截断问题(这是一个更大的问题)。不完全令人满意,但如果必须,我可以忍受。
  • 如果只有app:layout_constraintHorizontal_bias_MAX="1.0" 这样的东西应该会更容易。
  • 这个codeshorter text 工作,当text is longer 与按钮比较时,它将按钮居中。
  • @Enzokie - 是的,这行得通。和下面的Ben P.'s answer基本一样。

标签: android android-layout android-constraintlayout


【解决方案1】:

在我看来,这听起来像是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>

【讨论】:

  • 这很好地解决了布局问题。谢谢。虽然这有帮助,但我不能直接使用它,因为将文本视图和按钮分组会干扰事件处理。 (稀松布需要夹在 Z 中的顶部和底部视图之间。)
  • 稀松布的用途是什么?看起来它涵盖了整个父母,但我看不出你需要它做什么(因为在示例中它是透明的)。
  • 它在那里拦截底部视图之外的所有触摸事件。稀松布和底部视图同步改变可见性。当它们的可见性设置为VISIBLE 时,我希望在底部视图之外的任何点击都可以关闭底部视图和稀松布(可见性设置为GONE)。也有可能随着我们的应用程序的发展,稀松布将从透明变为半透明(当可见时)。正如我正在考虑的那样,也许我毕竟可以使用您的解决方案,通过修改顶部视图的单击处理程序以在底部视图/稀松布可见的情况下触发解除逻辑。丑陋,但它可能会起作用。
  • 另一种选择是基本上使用两个稀松布。一个在按钮和文本之间,另一个在该分组布局后面。单击其中任何一个都会关闭两者。
  • 是的,这样更干净。谢谢。
【解决方案2】:

假设有 2 个视图。

  • 选择第一个视图
  • shift
  • 选择第二个视图
  • 右击
  • 选择对齐 >> 水平中心

完成。

【讨论】:

  • 此解决方案不起作用。如果您通读该问题,您会发现问题在于,有时,根据视图的内容(在运行时会发生变化),视图必须相对于彼此居中.
【解决方案3】:

我没有完全理解你,但我发布了我所理解的答案。

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

【讨论】:

    【解决方案4】:

    我觉得可以试试

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

    【讨论】:

    • 据我所知,这只是在底部视图中添加 11dp 的右边距。这只会取消居中(当顶视图足够宽时)并且不会停止截断(当顶视图太窄时)。
    猜你喜欢
    • 2018-07-23
    • 1970-01-01
    • 2021-07-28
    • 1970-01-01
    • 1970-01-01
    • 2015-03-30
    • 1970-01-01
    • 1970-01-01
    • 2022-07-07
    相关资源
    最近更新 更多