ConstraintLayout,当依赖于约束的视图消失时,布局视图表现得很奇怪

Ely*_*lye 23 android android-layout android-constraintlayout

我正在使用ConstraintLayout,我将在下面显示

在此输入图像描述

我想隐藏First(使用已消失),以及我期望的视图如下所示(ElasticBody将延伸以使用原始First视图空间).

在此输入图像描述

但是,当我实际设置First为时gone,我的视图结果如下(所有图像都来自Android Studio Design视图).我Elastic Body也失踪了,高度奇怪地扩大了.

在此输入图像描述

我的布局代码如下

<android.support.constraint.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="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/txt_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0ff"
        android:text="First"
        android:visibility="gone"
        android:textSize="26sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/txt_body"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/txt_body"
        android:layout_width="0dp"
        android:background="#f0f"
        android:layout_height="wrap_content"
        android:text="Elastic Body"
        android:textSize="26sp"

        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toStartOf="@+id/txt_tail"
        app:layout_constraintStart_toEndOf="@+id/txt_first"
        app:layout_constraintTop_toTopOf="parent" />

    <TextView
        android:id="@+id/txt_tail"
        android:background="#ff0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tail"
        android:textSize="26sp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toEndOf="@+id/txt_body"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

(注意,如果你删除它gone,你将获得第一个图像视图).为什么会这样?我怎么能解决它在我First离开的地方,我可以Elastic Body伸展正确吗?

p/s:我知道如何在LinearLayout和RelativeLayout中做到这一点......但是想知道这是否是对ConstraintLayout的限制?

Meh*_*ria 23

您可以使用一件事Visibility.GONEConstraintLayout.你可以用Barriers它.

如果您不了解Barriers那么请检查:障碍

  • 如何利用障碍提高知名度? (10认同)
  • 由于链接失效,不鼓励在 StackOverflow 上仅发布链接答案。您应该包含一个工作示例,展示如何在问题的上下文中使用链接中的信息。在此处查看更多信息:https://meta.stackexchange.com/questions/225370/your-answer-is-in-another-castle-when-is-an-answer-not-an-answer (7认同)
  • 一个例子,如何做到这一点将是适当的。 (3认同)
  • @Vincent_Paing:这是一个示例链接https://constraintlayout.com/basics/barriers.html。 (2认同)

Coo*_*ind 9

比如说,你想要一张这样的图片:

在此处输入图片说明

Here you have indents between the title and "Nice work", between "Nice work" and time, also horizontal indent to "Opinions". They are centered vertically.

在此处输入图片说明

"Opinions" is attached to the star, so that can be multilined and stay centered. I show results for 2 variants: in the first row opinions are multilined, while in the next row it is a single line. In columns you can see 4 variants of showing/hiding 2 labels.

在此处输入图片说明

  1. A more simple and preferrable way is to wrap both labels into LinearLayout and insert it into parent ConstraintLayout. Then you can set vertical gravity, show or hide labels, hide the LinearLayout itself.

  2. If you don't want to have nested layouts, use Barriers and Groups. It is a difficult task that can waste many hours. A key is having additional Views for aligning. Here I have 2 hiding labels ("Nice work" and "Opinions"), and I have to add 2 views (spaces).

在此处输入图片说明

The height of the right space is equal to the height of the star (14dp).

To simplify hiding several views, I joined them into groups.

在此处输入图片说明

You can see horizontal dotted lines - they are Barriers. I align them on tops and bottoms of the most big views (barrier_2 is similar):

<androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier_1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    app:barrierDirection="top"
    app:constraint_referenced_ids="left_text,opinion" />
Run Code Online (Sandbox Code Playgroud)

在此处输入图片说明

Vertical aligning is based on these 2 additional Spaces (see marginTop="10dp"):

<Space
    android:id="@+id/left_text_space"
    android:layout_width="25dp"
    android:layout_height="10dp"
    android:layout_marginTop="10dp"
    app:layout_constraintStart_toEndOf="@id/left_text"
    app:layout_constraintTop_toBottomOf="@id/title" />
Run Code Online (Sandbox Code Playgroud)

It is difficult to cover all situations, so see the following layout:

<?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"
    android:paddingLeft="15dp"
    android:paddingTop="5dp"
    android:paddingRight="15dp"
    android:paddingBottom="5dp">

    <TextView
        android:id="@+id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:ellipsize="end"
        android:lineSpacingExtra="4sp"
        android:lines="1"
        android:paddingBottom="5dp"
        android:text="«Title text»"
        android:textColor="#333333"
        android:textSize="15sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier_1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="top"
        app:constraint_referenced_ids="left_text,opinion" />

    <TextView
        android:id="@+id/left_text"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#112233"
        android:paddingLeft="5dp"
        android:paddingTop="4dp"
        android:paddingRight="5dp"
        android:paddingBottom="4dp"
        android:text="Nice work"
        android:textColor="#ffffff"
        android:textSize="13sp"
        app:layout_constraintBottom_toBottomOf="@id/barrier_2"
        app:layout_constraintStart_toStartOf="@id/title"
        app:layout_constraintTop_toTopOf="@id/left_text_space" />

    <Space
        android:id="@+id/left_text_space"
        android:layout_width="25dp"
        android:layout_height="10dp"
        android:layout_marginTop="10dp"
        app:layout_constraintStart_toEndOf="@id/left_text"
        app:layout_constraintTop_toBottomOf="@id/title" />

    <androidx.constraintlayout.widget.Group
        android:id="@+id/left_text_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="visible"
        app:constraint_referenced_ids="left_text,left_text_space" />

    <Space
        android:id="@+id/opinion_space"
        android:layout_width="1dp"
        android:layout_height="14dp"
        android:layout_marginTop="10dp"
        app:layout_constraintStart_toStartOf="@id/left_text_space"
        app:layout_constraintTop_toBottomOf="@id/title" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier_2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="bottom"
        app:constraint_referenced_ids="left_text,opinion" />

    <ImageView
        android:id="@+id/opinion_icon"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center_vertical"
        android:contentDescription="@null"
        app:layout_constraintBottom_toBottomOf="@id/barrier_2"
        app:layout_constraintStart_toEndOf="@id/left_text_space"
        app:layout_constraintTop_toTopOf="@id/opinion_space"
        app:srcCompat="@drawable/ic_filled_rate_star" />

    <TextView
        android:id="@+id/opinion"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="5dp"
        android:layout_marginLeft="5dp"
        android:lineSpacingExtra="1sp"
        android:text="1. Opinion 1.\n2. Opinion 2.\n3. Opinion 3.\n4. Opinion 4."
        android:textColor="#1122aa"
        android:textSize="12sp"
        app:layout_constraintBottom_toBottomOf="@id/opinion_icon"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@id/opinion_icon"
        app:layout_constraintTop_toTopOf="@id/opinion_icon" />

    <androidx.constraintlayout.widget.Group
        android:id="@+id/opinion_group"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:visibility="visible"
        app:constraint_referenced_ids="opinion_icon,opinion,opinion_space" />

    <ImageView
        android:id="@+id/time_icon"
        android:layout_width="15dp"
        android:layout_height="15dp"
        android:layout_gravity="center_vertical"
        android:layout_marginTop="8dp"
        android:contentDescription="@null"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/barrier_2"
        app:srcCompat="@drawable/ic_time" />

    <TextView
        android:id="@+id/time"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginStart="7dp"
        android:layout_marginLeft="7dp"
        android:ellipsize="end"
        android:lineSpacingExtra="1sp"
        android:lines="2"
        android:paddingBottom="7dp"
        android:text="17:00"
        android:textColor="#9e9e9e"
        android:textSize="11sp"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintHorizontal_weight="1"
        app:layout_constraintStart_toEndOf="@id/time_icon"
        app:layout_constraintTop_toTopOf="@id/time_icon" />

</androidx.constraintlayout.widget.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

Then in your activity you can show/hide labels. Hide Groups, not views inside, because strangely inside a Group views are always visible.

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.main_activity)

    left_text_group.visibility = View.GONE
    opinion_group.visibility = View.VISIBLE
}
Run Code Online (Sandbox Code Playgroud)


Vuc*_*cko 8

已经给出了链接到Barriers 的答案。我将提供一个示例来说明我如何实际实现它:

<TextView
    android:id="@+id/textView1"
    app:layout_constraintTop_toBottomOf="parent"
    app:layout_constraintLeft_toLeftOf="parent"
    android:text="Some text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />

<TextView
    android:id="@+id/textView2"
    app:layout_constraintTop_toBottomOf="@id/textView1"
    app:layout_constraintLeft_toLeftOf="parent"
    android:text="Some other text"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content" />
<androidx.constraintlayout.widget.Barrier
    android:id="@+id/barrier1"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:orientation="horizontal"
    app:barrierDirection="bottom"
    app:constraint_referenced_ids="textView1,textView2" />
Run Code Online (Sandbox Code Playgroud)

此示例显示 2 TextViews,其中任意一个都可以是gone。视图从上到下堆叠,因此barrierDirection设置为bottom。如果您需要另一个方向,只需相应地更改该行即可。

将 2 中的任何一个设置TextViewsgone, 将导致Barrier移动到另一个的底部,如果我们将两者都设置为gone,它只会向上移动到 的顶部约束引用的元素textView1,在本例中为父元素。

注意:如果您的textView1顶部约束是其他内容,即它位于另一个元素下方,则如果两个视图都设置为 ,障碍物将在那里结束gone


Shw*_*han 5

参见输出:

请尝试以下。

将第一个视图的左侧和顶部约束设置为“父”。之后:

  • 将主体视图宽度设置为“ 0dp”
  • 将左约束设置为第一个视图的右侧
  • 将右约束设置到尾视图的左侧。

因此,每当您将第一个视图的可见性设置为“ gone”时,主体视图就会像您希望的那样被拉伸。

<android.support.constraint.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="wrap_content"
    android:padding="16dp">

    <TextView
        android:id="@+id/txt_first"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:background="#0ff"
        android:text="First"
        android:textSize="26sp"
        android:visibility="gone"
        app:layout_constraintEnd_toStartOf="@+id/txt_body"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent" />

    <TextView
        android:id="@+id/txt_body"
        android:layout_width="0dp"
        android:background="#f0f"
        android:layout_height="wrap_content"
        android:text="Elastic Body"
        android:textSize="26sp"
        app:layout_constraintRight_toLeftOf="@+id/txt_tail"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/txt_first"
        />

    <TextView
        android:id="@+id/txt_tail"
        android:background="#ff0"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Tail"
        android:textSize="26sp"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toRightOf="parent" />

</android.support.constraint.ConstraintLayout>
Run Code Online (Sandbox Code Playgroud)

  • 拒绝投票可能是因为您说了“试试看”,并显示了很多代码。您所做的工作没有任何解释,甚至没有突出显示有意义的代码行。但是后来我猜到了,因为我没有做过否决票。因此,请添加一些有关您的建议的评论,因为阅读代码很烂。 (28认同)
  • 对其进行投票,因为它仍然是答案和努力 (2认同)