[學習]android 中的 ConstraintLayout 布局(二)

Barrier 和 Chains

如果選擇使用,一定要看明白,不要漏掉屬性,否則你到時候會發(fā)狂的。

1. Barrier

是一個準則,可以說是對其的規(guī)則,這樣說還不夠名義,我們可以列表一些比較常見的場景;
官網(wǎng) Barrier

  1. 具體看圖
    簡單的布局

    “第二行的label”和“第二行value”是一個整體,他們距離上面是 100dp ,但是有可能“第二行value”的值為空或者是空,也需要“第二行l(wèi)abel”距離上面的距離是 100dp ,由于我們知道“第二行value”的高度高于第一個,所以采用的是“第二行l(wèi)abel”跟“第二行value”對其,“第二行value”距離上邊 100dp 的距離,但是由于“第二行value”有可能為空,所以當“第二行value”為空的時候就會出現(xiàn)下面的效果:
    “第二行value”消失的效果

    我們發(fā)現(xiàn)達不到預期,現(xiàn)在能想到的辦法有,首先在代碼控制的時候隨便把“第二行l(wèi)abel”的 marginTop 也添加進去;還有就是換布局,將“第二行l(wèi)abel”和“第二行value”放到一個布局中,比如 LinearLayout ,這樣上邊的 marginTopLinearLayout 控制;這樣的話即便“第二行value”消失了也會保持上邊的效果。

除了上邊的方法還能使用其他的嘛,比如我們不使用代碼控制,我們不使用其他的布局,因為我們知道布局嵌套太多性能也會相應的下降,所以在編寫的時候能減少嵌套的情況下盡可能的減少,當然也不能為了減少嵌套讓代碼變得格外的復雜。

為了滿足上面的需求, Barrier 出現(xiàn)了,它能做到隱藏的也能依靠它,并且與它的距離保持不變對于隱藏的“第二行value”來說,雖然消失了,但保留了 marginTop 的數(shù)值。下面看看布局:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

  <TextView
      android:id="@+id/textView4"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:text="頭部"
      android:textSize="36sp"
      app:layout_constraintBottom_toTopOf="@id/barrier3"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />


  <androidx.constraintlayout.widget.Barrier
      android:id="@+id/barrier3"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:barrierDirection="top"
      android:layout_marginTop="100dp"
      app:constraint_referenced_ids="textView2,textView3" />

  <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="4dp"
      android:text="第二行l(wèi)abel"
      android:textSize="36sp"
      app:layout_constraintBottom_toBottomOf="@+id/textView3"
      app:layout_constraintStart_toStartOf="@+id/textView4"
      app:layout_constraintTop_toTopOf="@+id/textView3"
      app:layout_constraintVertical_bias="0.538" />

  <TextView
      android:id="@+id/textView3"
      android:layout_width="wrap_content"
      android:layout_height="100dp"
      android:layout_marginStart="12dp"
      android:layout_marginTop="100dp"
      android:text="第二行value"
      android:textSize="36sp"
      app:layout_constraintStart_toEndOf="@+id/textView2"
      app:layout_constraintTop_toBottomOf="@+id/barrier3" />

</androidx.constraintlayout.widget.ConstraintLayout>

這樣即便將“第二行value”消失,那么總體的布局仍然達到預期,并且也沒有添加很多布局內(nèi)容。在代碼中:

<androidx.constraintlayout.widget.Barrier
      android:id="@+id/barrier3"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:barrierDirection="top"
      android:layout_marginTop="100dp"
      app:constraint_referenced_ids="textView2,textView3" />

這里主要有兩個屬性 app:barrierDirectionapp:constraint_referenced_ids

  • app:barrierDirection 是代表位置,也就是在包含內(nèi)容的哪一個位置,我這里寫的是 top ,是在頂部,還有其他的屬性 top,bottom,left,right,startend 這幾個屬性,看意思就很明白了。
  • app:constraint_referenced_ids 上面說的內(nèi)容就是包含在這里面的,這里面填寫的是 id 的名稱,如果有多個,那么使用逗號隔開;這里面的到 Barrier 的距離不會改變,即便隱藏了也不會變。

這里可能會有疑惑,為啥我寫的 idtextView4 的也依賴于 Barrier ,這是因為本身 Barrier 只是規(guī)則不是實體,它的存在只能依附于實體,不能單獨存在于具體的位置,如果我們只有“第二行value”依賴于它,但是本身“第二行value”沒有上依賴,也相當于沒有依賴,這樣只會導致“第二行l(wèi)abel”和“第二行value”都消失,如果 textView4 依賴于 Barrier ,由于 textView4 的位置是確定的,所以 Barrier 的位置也就確定了。

  1. 類似表格的效果??床季中Ч?/p>

    表格的樣式

    我要做成上面的樣子。也就是右邊永遠與左邊最長的保持距離。下面是我的代碼:

<?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"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">


  <TextView
      android:id="@+id/textView4"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="8dp"
      android:text="頭部"
      android:textSize="36sp"
      app:layout_constraintStart_toStartOf="parent"
      app:layout_constraintTop_toTopOf="parent" />

  <TextView
      android:id="@+id/textView2"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="4dp"
      android:text="第二行"
      android:textSize="36sp"
      app:layout_constraintBottom_toBottomOf="@+id/textView3"
      app:layout_constraintStart_toStartOf="@+id/textView4"
      app:layout_constraintTop_toTopOf="@+id/textView3" />

  <TextView
      android:id="@+id/textView3"
      android:layout_width="wrap_content"
      android:layout_height="50dp"
      android:layout_marginStart="20dp"
      android:layout_marginTop="10dp"
      android:text="第二行value"
      android:textSize="36sp"
      app:layout_constraintStart_toEndOf="@+id/barrier4"
      app:layout_constraintTop_toBottomOf="@+id/textView4" />


  <TextView
      android:id="@+id/textView5"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      android:layout_marginStart="4dp"
      android:text="第三次測試"
      android:textSize="36sp"
      app:layout_constraintBottom_toBottomOf="@+id/textView6"
      app:layout_constraintStart_toStartOf="@+id/textView4"
      app:layout_constraintTop_toTopOf="@+id/textView6" />

  <TextView
      android:id="@+id/textView6"
      android:layout_width="wrap_content"
      android:layout_height="50dp"
      android:layout_marginStart="20dp"
      android:layout_marginTop="10dp"
      android:text="第三行value"
      android:textSize="36sp"
      app:layout_constraintStart_toEndOf="@+id/barrier4"
      app:layout_constraintTop_toBottomOf="@+id/textView3" />

  <androidx.constraintlayout.widget.Barrier
      android:id="@+id/barrier4"
      android:layout_width="wrap_content"
      android:layout_height="wrap_content"
      app:barrierDirection="end"
      app:constraint_referenced_ids="textView2,textView5"
      tools:layout_editor_absoluteX="411dp" />


</androidx.constraintlayout.widget.ConstraintLayout>

添加好了,記得讓右邊的約束指向 Barrier 。這里的 Barrier ,我們看到包含 textView2textView5 ,這個時候就能做到誰長聽誰的,如果此時 textView2 變長了,那么就會將就 textView2 。

2. Chains

我們特別喜歡使用線性布局,因為我們發(fā)現(xiàn) UI 圖上的效果使用線性布局都可以使用,當然也有可能跟大部分人的思維方式有關系。比如我們非常喜歡的,水平居中,每部分的空間分布等等都非常的順手。既然線性布局這么好用,那為啥還有約束布局呢,因為線性布局很容易寫出嵌套很深的布局,但約束布局不會,甚至大部分情況都可以不需要嵌套就能實現(xiàn),那是不是代表線性布局有的約束布局也有,答案是肯定的。

使用普通的約束關系就很容易實現(xiàn)水平居中等常用效果,其他的如水平方向平均分布空間,使用一般的約束是實現(xiàn)不了的,于是就要使用 Chains ,這個就很容易實現(xiàn)下面的效果:

可以達到的效果

其實上一篇中我已經(jīng)把官網(wǎng)的教程貼上去了,這里主要寫雙向約束怎么做,一旦雙向約束形成,那么就自然進入到 Chains 模式。

1)在視圖模式中操作


默認的情況

如果直接操作,那么只能單向約束,如果要形成這樣的約束,需要選擇相關的的節(jié)點,比如我這里就是同時選擇 AB ,然后點擊鼠標右鍵,就可以看到 ChainsCreate Horizontal Chain 。

對應的操作

選擇圖中的選項即可完成從 A 指向 B ,修改的示意圖為:

鼠標右鍵示意圖

我們發(fā)現(xiàn)已經(jīng)實現(xiàn)了水平方向的排列效果了。至于怎么實現(xiàn)上面的效果,主要是改變 layout_constraintVertical_chainStylelayout_constraintHorizontal_chainStyle 屬性。至于權重則是屬性 layout_constraintHorizontal_weight 。

layout_constraintHorizontal_chainStyle 屬性說明:

  • spread 默認選項,效果就是上面的那種,也就是平均分配剩余空間;
  • spread_inside 兩邊的緊挨著非 Chains 的視圖,中間的平均分配;
    spread_inside的效果圖
  • packed 所有的都在中間
    packed效果圖

    注意了, layout_constraintHorizontal_weight 這個屬性只有在 A 身上設置才可以,也就是首節(jié)點上設置才可行,同時 layout_constraintHorizontal_weight 是代表水平方向,只能在水平方向才發(fā)生作用,如果水平的設置了垂直則不生效。

layout_constraintHorizontal_weight 這個屬性只有在當前視圖的寬或者高是 0dp 。至于這個的取值跟線性布局相同。

我設置B的layout_constraintHorizontal_weight屬性值為1的效果

2)代碼的方式
跟上面的差別就是在做雙向綁定,用代碼就很容易實現(xiàn)雙向綁定,可平時添加約束相同。

最后編輯于
?著作權歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

友情鏈接更多精彩內(nèi)容