簡體   English   中英

ConstraintLayout,當約束依賴視圖消失時,布局視圖行為怪異

[英]ConstraintLayout, when constraint dependent view is gone, the layout view behave weirdly

我正在使用 ConstraintLayout 我將顯示如下

在此處輸入圖像描述

我想隱藏First (使用gone),以及我希望如下所示的視圖(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>

(注意,如果你刪除了gone ,你會得到第一個圖像視圖)。 為什么會這樣? 當我的First消失時,我該如何修復它,我可以正確伸展Elastic Body

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

您可以在ConstraintLayout中為Visibility.GONE使用的另一件事是: Barriers

如果您不了解Barriers ,請檢查:障礙

見輸出:

嘗試跟隨。

將第一個視圖的左側和頂部約束設置為“父級”。 在那之后:

  • 將 txt_body 文本視圖寬度設置為“0dp”
  • 將左側約束設置為第一個視圖的右側
  • 將右約束設置為尾視圖的左側。

因此,每當您將第一個視圖的可見性設置為“已消失”時,主體視圖將按照您想要的方式進行拉伸。

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

更新

如果你想使用屏障,那么你也可以這樣做。

<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="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/barrier"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

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

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

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="start"
        app:constraint_referenced_ids="txt_body,txt_first" />

    <androidx.constraintlayout.widget.Barrier
        android:id="@+id/barrier1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:barrierDirection="end"
        app:constraint_referenced_ids="txt_body,txt_tail" />

</androidx.constraintlayout.widget.ConstraintLayout>

說,你想要這樣的圖片:

在此處輸入圖像描述

在這里,標題和“好作品”之間、“好作品”和時間之間有縮進,“意見”也有水平縮進。 它們垂直居中。

在此處輸入圖像描述

“意見”附在星號上,因此可以多線並保持居中。 我展示了 2 個變體的結果:第一行意見是多行的,而下一行是單行。 在列中,您可以看到顯示/隱藏 2 個標簽的 4 個變體。

在此處輸入圖像描述

  1. 一種更簡單、更可取的方法是將兩個標簽都包裝到LinearLayout中,然后將其插入到父級ConstraintLayout中。 然后你可以設置垂直重力,顯示或隱藏標簽,隱藏LinearLayout本身。

  2. 如果您不想嵌套布局,請使用BarrierGroup 這是一項艱巨的任務,可能會浪費很多時間。 一個關鍵是有額外的View用於對齊。 在這里,我有 2 個隱藏標簽(“Nice work”和“Opinions”),我必須添加 2 個視圖(空格)。

在此處輸入圖像描述

右邊空間的高度等於星星的高度(14dp)。

為了簡化隱藏多個視圖,我將它們加入到組中。

在此處輸入圖像描述

您可以看到水平虛線 - 它們是Barrier 我將它們對齊在最大視圖的頂部和底部(barrier_2 類似):

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

在此處輸入圖像描述

垂直對齊基於這 2 個額外的Space (參見 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" />

很難涵蓋所有情況,所以請看下面的布局:

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

然后在您的活動中,您可以顯示/隱藏標簽。 隱藏Group s,而不是內部的視圖,因為奇怪的是Group內部的視圖總是可見的。

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

    left_text_group.visibility = View.GONE
    opinion_group.visibility = View.VISIBLE
}

已經給出了鏈接到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" />

此示例顯示了 2 個TextViews ,其中任何一個都可以gone 視圖從上到下堆疊,因此barrierDirection設置為bottom 如果您需要另一個方向,只需相應地更改該行。

將 2 個TextViews中的任何一個設置為gone ,將導致Barrier移動到另一個的底部,如果我們將兩者都設置為gone ,它只會向上移動到textView1的頂部約束所引用的元素,在此案例,家長。

注意:如果你的textView1的頂部約束是別的東西,即它在另一個元素之下,如果兩個視圖gone設置為,屏障將在那里結束。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM