<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          ConstraintLayout使用場(chǎng)景必知必會(huì)

          共 3542字,需瀏覽 8分鐘

           ·

          2021-01-29 12:19

          ConstraintLayout的布局優(yōu)越性已經(jīng)不用再?gòu)?qiáng)調(diào)了,通過(guò)ConstraintLayout的約束思想,可以很方便的解決一些之前需要寫(xiě)很復(fù)雜的動(dòng)態(tài)代碼才能完成的效果。

          早在2016年,我就已經(jīng)逐漸將項(xiàng)目中的布局進(jìn)行約束化,采用ConstraintLayout來(lái)替換原有布局,同時(shí)對(duì)ConstraintLayout的基礎(chǔ)使用,進(jìn)行了總結(jié),感興趣的入門(mén)開(kāi)發(fā)者可以參考下面的文章。

          https://blog.csdn.net/eclipsexys/article/details/52609367

          國(guó)際慣例,官網(wǎng)鎮(zhèn)樓,這是入門(mén)ConstraintLayout最好的資料。

          https://developer.android.com/training/constraint-layout?hl=zh-cn

          當(dāng)然,ConstraintLayout并不是解決所有布局問(wèn)題的銀彈,在下面的這些場(chǎng)景下使用,可以算得上ConstraintLayout的最佳實(shí)踐,可以達(dá)到事半功倍的效果。

          固定比例視圖

          考慮下面這個(gè)場(chǎng)景,組件寬度撐滿(mǎn)屏幕,高度按「寬度x固定比例」計(jì)算。

          這樣的布局,在以往的布局方式下,都需要通過(guò)動(dòng)態(tài)計(jì)算后修改高度來(lái)實(shí)現(xiàn),但是通過(guò)ConstraintLayout,則可以直接在XML中實(shí)現(xiàn)。

          ????android:layout_width="match_parent"
          ????android:layout_height="@dimen/length_0"
          ????app:layout_constraintDimensionRatio="1:0.34"
          ????app:layout_constraintStart_toStartOf="parent"
          ????app:layout_constraintTop_toTopOf="parent"?/>

          通過(guò)DimensionRatio,可以很方便的實(shí)現(xiàn)比例視圖的控制,同時(shí),比例可以設(shè)置的很靈活,滿(mǎn)足各種條件的需要。

          N等分布局

          常見(jiàn)的N等分布局,例如三等分布局,通常都需要進(jìn)行動(dòng)態(tài)計(jì)算,根據(jù)屏幕寬度,減去間距后得到每部分的寬度,再動(dòng)態(tài)設(shè)置給每個(gè)元素,而通過(guò)ConstraintLayout,則可以直接實(shí)現(xiàn)這樣的效果。

          "1.0"?encoding="utf-8"?>
          "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="wrap_content"
          ????android:layout_marginLeft="@dimen/length_16"
          ????android:layout_marginRight="@dimen/length_16">

          ????????????android:id="@+id/bookCover1"
          ????????android:layout_width="0dp"
          ????????android:layout_height="0dp"
          ????????app:layout_constraintDimensionRatio="0.74:1"
          ????????app:layout_constraintEnd_toStartOf="@+id/bookCover2"
          ????????app:layout_constraintHorizontal_chainStyle="spread_inside"
          ????????app:layout_constraintStart_toStartOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"
          ????????app:layout_constraintWidth_percent="0.30"
          ????????tools:srcCompat="@tools:sample/avatars"?/>

          ????????????android:id="@+id/bookCover2"
          ????????android:layout_width="0dp"
          ????????android:layout_height="0dp"
          ????????android:visibility="invisible"
          ????????app:layout_constraintDimensionRatio="0.74:1"
          ????????app:layout_constraintEnd_toStartOf="@+id/bookCover3"
          ????????app:layout_constraintStart_toEndOf="@+id/bookCover1"
          ????????app:layout_constraintTop_toTopOf="@+id/bookCover1"
          ????????app:layout_constraintWidth_percent="0.30"
          ????????tools:srcCompat="@tools:sample/avatars"?/>

          ????????????android:id="@+id/bookCover3"
          ????????android:layout_width="0dp"
          ????????android:layout_height="0dp"
          ????????app:layout_constraintDimensionRatio="0.74:1"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintStart_toEndOf="@+id/bookCover2"
          ????????app:layout_constraintTop_toTopOf="@+id/bookCover2"
          ????????app:layout_constraintWidth_percent="0.30"
          ????????tools:srcCompat="@tools:sample/avatars"?/>


          效果如下圖所示。

          image-20201231134812154

          這其中的間距,主要是通過(guò)layout_constraintWidth_percent來(lái)設(shè)置在當(dāng)前容器尺寸下所占百分比來(lái)進(jìn)一步約束大小。

          如果去掉這個(gè)屬性,那么會(huì)直接等分父容器尺寸。

          image-20201231135224309

          另外,還可以通過(guò)layout_constraintHorizontal_weight屬性來(lái)控制類(lèi)似LinearLayout的weight屬性的效果,實(shí)現(xiàn)按權(quán)重進(jìn)行分配。

          image-20201231135427254

          復(fù)雜的元素相對(duì)居中

          在整個(gè)View中,針對(duì)某個(gè)固定元素,其它的元素圍繞它做的各種對(duì)齊方式,在之前是很難直接完成的,即使是使用-margin的方式,也很難實(shí)現(xiàn)動(dòng)態(tài)可變尺寸的居中,而在ConstraintLayout中,這就變得很簡(jiǎn)單了。

          image-20201231140237564

          代碼就不貼了,ConstraintLayout基操。

          百分比對(duì)齊

          在ConstraintLayout中,雖然不能使用-margin的方式來(lái)完成傳統(tǒng)布局中的一些錯(cuò)位的效果,但是可以借助Space來(lái)實(shí)現(xiàn)類(lèi)似的功能,例如借助Space來(lái)實(shí)現(xiàn)左邊TextView在右邊TextView某一百分比(或者是dp)對(duì)齊的場(chǎng)景。

          image-20201231144811750

          代碼如下所示。

          "1.0"?encoding="utf-8"?>
          "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">

          ????????????android:id="@+id/textView2"
          ????????android:layout_width="200dp"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginTop="32dp"
          ????????android:layout_marginEnd="32dp"
          ????????android:background="#bebebe"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/space"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????app:layout_constraintEnd_toEndOf="@+id/textView2"
          ????????app:layout_constraintHorizontal_bias="0.2"
          ????????app:layout_constraintStart_toStartOf="@+id/textView2"
          ????????tools:layout_editor_absoluteY="68dp"?/>

          ????????????android:id="@+id/textView3"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toStartOf="@+id/space"
          ????????tools:layout_editor_absoluteY="92dp"?/>
          ????

          由于ConstraintLayout不支持-Margin,所以很多場(chǎng)景下,我們都可以借助Space等輔助元素來(lái)實(shí)現(xiàn)中轉(zhuǎn),完成傳統(tǒng)布局下通過(guò)-Margin實(shí)現(xiàn)的效果。

          角度布局

          通過(guò)角度的方式來(lái)對(duì)元素進(jìn)行排列,在傳統(tǒng)布局中,只能通過(guò)FrameLayout,并通過(guò)動(dòng)態(tài)計(jì)算的方式,將角度換算為邊距的方式來(lái)布局,但通過(guò)ConstraintLayout,則變的非常簡(jiǎn)單。

          "1.0"?encoding="utf-8"?>
          "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:id="@+id/textView1"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:text="Center"
          ????????app:layout_constraintBottom_toBottomOf="parent"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintStart_toStartOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/textView2"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:text="30"
          ????????app:layout_constraintBottom_toTopOf="@+id/textView1"
          ????????app:layout_constraintCircle="@id/textView1"
          ????????app:layout_constraintCircleAngle="30"
          ????????app:layout_constraintCircleRadius="100dp"
          ????????app:layout_constraintStart_toEndOf="@+id/textView1"?/>

          ????????????android:id="@+id/textView3"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:text="60"
          ????????app:layout_constraintBottom_toTopOf="@+id/textView1"
          ????????app:layout_constraintCircle="@id/textView1"
          ????????app:layout_constraintCircleAngle="60"
          ????????app:layout_constraintCircleRadius="100dp"
          ????????app:layout_constraintStart_toEndOf="@+id/textView1"?/>

          ????????????android:id="@+id/textView4"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:text="90"
          ????????app:layout_constraintBottom_toTopOf="@+id/textView1"
          ????????app:layout_constraintCircle="@id/textView1"
          ????????app:layout_constraintCircleAngle="90"
          ????????app:layout_constraintCircleRadius="100dp"
          ????????app:layout_constraintStart_toEndOf="@+id/textView1"?/>


          image-20201231141025307

          這種布局的方式,涉及的屬性如下。

          layout_constraintCircleAngle
          layout_constraintCircleRadius
          layout_constraintStart_toEndOf

          通過(guò)這幾個(gè)屬性就可以很方便的按照角度坐標(biāo)來(lái)進(jìn)行布局。

          整體居中

          通過(guò)Chain可以實(shí)現(xiàn)多個(gè)元素在邊緣約束的場(chǎng)景下居中的效果,如圖所示。

          image-20201231141433244

          這也是ConstraintLayout基操,不細(xì)說(shuō)了。

          超長(zhǎng)限制強(qiáng)制約束

          考慮下面這個(gè)場(chǎng)景,最下面的TextView最大不會(huì)超過(guò)第一個(gè)TextView的寬度。

          image-20201231143217743
          "1.0"?encoding="utf-8"?>
          "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:id="@+id/textView2"
          ????????android:layout_width="300dp"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginTop="32dp"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintStart_toStartOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/textView3"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginTop="32dp"
          ????????android:ellipsize="end"
          ????????android:singleLine="true"
          ????????android:text="TextViewTextViewTextViewTextViewTextViewTextViewTextViewTextViewTextViewTextView"
          ????????app:layout_constrainedWidth="true"
          ????????app:layout_constraintEnd_toEndOf="@+id/textView2"
          ????????app:layout_constraintHorizontal_bias="0.0"
          ????????app:layout_constraintStart_toStartOf="@+id/textView2"
          ????????app:layout_constraintTop_toBottomOf="@+id/textView2"?/>
          ????

          效果如下所示。

          image-20201231143324612

          這時(shí)候就需要通過(guò)使用constrainedWidth來(lái)使其寬度約束強(qiáng)制生效。

          類(lèi)似的,再考慮下面這個(gè)場(chǎng)景。

          image-20201231143946634

          當(dāng)?shù)诙€(gè)TextView文字超長(zhǎng)的時(shí)候,希望它截?cái)啵粫?huì)影響左右的TextView。這個(gè)場(chǎng)景非常常用,在很多業(yè)務(wù)場(chǎng)景下都會(huì)使用到這樣的功能,傳統(tǒng)布局下,只能在布局時(shí)動(dòng)態(tài)計(jì)算文字寬度來(lái)進(jìn)行動(dòng)態(tài)修改,但通過(guò)ConstraintLayout,則可以非常方便的實(shí)現(xiàn)。

          "1.0"?encoding="utf-8"?>
          "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:id="@+id/textView4"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginStart="32dp"
          ????????android:layout_marginTop="32dp"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toStartOf="@+id/textView5"
          ????????app:layout_constraintHorizontal_bias="0.0"
          ????????app:layout_constraintHorizontal_chainStyle="packed"
          ????????app:layout_constraintStart_toStartOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/textView5"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginStart="16dp"
          ????????android:layout_marginEnd="16dp"
          ????????android:ellipsize="end"
          ????????android:singleLine="true"
          ????????android:text="TextView"
          ????????app:layout_constrainedWidth="true"
          ????????app:layout_constraintEnd_toStartOf="@+id/textView6"
          ????????app:layout_constraintHorizontal_bias="0.5"
          ????????app:layout_constraintStart_toEndOf="@+id/textView4"
          ????????app:layout_constraintTop_toTopOf="@+id/textView4"?/>

          ????????????android:id="@+id/textView6"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginEnd="32dp"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintHorizontal_bias="0.5"
          ????????app:layout_constraintStart_toEndOf="@+id/textView5"
          ????????app:layout_constraintTop_toTopOf="@+id/textView5"?/>
          ????

          image-20201231144005478

          多組件協(xié)同約束

          考慮下面這個(gè)場(chǎng)景,多個(gè)組件的寬度不定,需要取最大寬度的組件在布局中展示,例如下面這個(gè)例子。

          Email和Password兩個(gè)TextView的寬度可能因?yàn)槲淖值牟灰粯佣煌枰麄冋w取最大寬度后,與右邊元素進(jìn)行對(duì)齊,如下所示。

          image-20210127161500403

          這時(shí)候,就需要使用Barrier。Barrier可以理解為一個(gè)柵欄,Barrier和Group一樣,通過(guò)constraint_referenced_ids來(lái)組合需要作用的組件,代碼如下。

          "1.0"?encoding="utf-8"?>
          "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="wrap_content">

          ????????????android:id="@+id/email"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginBottom="8dp"
          ????????android:textSize="24sp"
          ????????app:layout_constraintBottom_toTopOf="@+id/password"
          ????????app:layout_constraintStart_toStartOf="@+id/password"
          ????????app:layout_constraintTop_toTopOf="parent"
          ????????app:layout_constraintVertical_chainStyle="packed"
          ????????tools:text="E-mail?Address"?/>

          ????????????android:id="@+id/emailInput"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginStart="8dp"
          ????????android:ems="10"
          ????????android:inputType="textEmailAddress"
          ????????android:text="[email protected]"
          ????????app:layout_constraintBaseline_toBaselineOf="@+id/email"
          ????????app:layout_constraintStart_toEndOf="@+id/barrier"?/>

          ????????????android:id="@+id/password"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginTop="8dp"
          ????????android:text="Password"
          ????????android:textSize="24sp"
          ????????app:layout_constraintBottom_toBottomOf="parent"
          ????????app:layout_constraintTop_toBottomOf="@+id/email"
          ????????tools:layout_editor_absoluteX="11dp"?/>

          ????????????android:id="@+id/passwordInput"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginStart="8dp"
          ????????android:ems="10"
          ????????android:inputType="textPassword"
          ????????android:text="666666"
          ????????app:layout_constraintBaseline_toBaselineOf="@+id/password"
          ????????app:layout_constraintStart_toEndOf="@+id/barrier"?/>

          ????????????android:id="@+id/barrier"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="wrap_content"
          ????????app:barrierDirection="right"
          ????????app:constraint_referenced_ids="email,password"?/>


          其中barrierDirection設(shè)置為right,即右側(cè)不超過(guò)Barrier,再讓剩余組件與Barrier進(jìn)行約束即可。

          容器約束下的邊界約束

          考慮下面這個(gè)場(chǎng)景,中間的TextView被約束在兩邊的組件中,如下所示。

          image-20201231145935870
          "1.0"?encoding="utf-8"?>
          "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">

          ????????????android:id="@+id/textView4"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="100dp"
          ????????android:layout_marginStart="32dp"
          ????????android:layout_marginTop="32dp"
          ????????android:background="#bebebe"
          ????????android:text="TextView"
          ????????app:layout_constraintStart_toStartOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/textView5"
          ????????android:layout_width="wrap_content"
          ????????android:layout_height="100dp"
          ????????android:layout_marginTop="32dp"
          ????????android:layout_marginEnd="32dp"
          ????????android:background="#bebebe"
          ????????android:text="TextView"
          ????????app:layout_constraintEnd_toEndOf="parent"
          ????????app:layout_constraintTop_toTopOf="parent"?/>

          ????????????android:id="@+id/textView6"
          ????????android:layout_width="0dp"
          ????????android:layout_height="wrap_content"
          ????????android:layout_marginStart="16dp"
          ????????android:layout_marginEnd="16dp"
          ????????android:text="TextViewTextViewTextViewTextViewTextViewTextView"
          ????????app:layout_constraintEnd_toStartOf="@+id/textView5"
          ????????app:layout_constraintStart_toEndOf="@+id/textView4"
          ????????tools:layout_editor_absoluteY="73dp"?/>


          在個(gè)例子的重點(diǎn)是將layout_width設(shè)置為0dp,即MATCH_CONSTRAINT,即可實(shí)現(xiàn)這樣的效果。

          下面進(jìn)一步思考下這個(gè)場(chǎng)景。

          當(dāng)TextView文字較少時(shí),可以發(fā)現(xiàn)其尺寸是默認(rèn)占據(jù)了整個(gè)約束空間,這時(shí)候,如果要求TextView只顯示文字大小,類(lèi)似設(shè)置wrap_content的效果,但是在文字長(zhǎng)的時(shí)候,又必須被邊緣約束,所以又不能設(shè)置wrap_content,這種場(chǎng)景下,可以通過(guò)layout_constraintWidth_default屬性來(lái)解決,它提供了邊緣約束下默認(rèn)的尺寸設(shè)置方式。

          前面說(shuō)的類(lèi)似wrap_content的效果,就可以使用wrap來(lái)設(shè)置。

          app:layout_constraintWidth_default="wrap"
          image-20201231151918340

          當(dāng)然,不設(shè)置這個(gè)屬性,將TextView的寬度設(shè)置為wrap_content,也是可以實(shí)現(xiàn)這個(gè)效果的,這就需要使用到前面講的constrainedWidth屬性了。

          layout_constraintWidth_default的默認(rèn)值為spread,即占據(jù)邊緣約束下的所有空間。

          總結(jié)

          ConstraintLayout的學(xué)習(xí)曲線(xiàn)比較陡峭,入門(mén)很簡(jiǎn)單,想要寫(xiě)好,卻是很難的,大部分的開(kāi)發(fā)者在經(jīng)過(guò)一段時(shí)間的學(xué)習(xí)后,都可以上手進(jìn)行布局,但是遇到一些比較復(fù)雜的業(yè)務(wù)場(chǎng)景時(shí),就很難將ConstraintLayout的這些特性融會(huì)貫通了,所以,使用ConstraintLayout,有下面這些準(zhǔn)則。

          • 找準(zhǔn)布局基準(zhǔn)元素,一般是界面的固定不變的業(yè)務(wù)元素,其它組件,根據(jù)其約束來(lái)進(jìn)行布局
          • 使用Group等虛擬布局組件來(lái)簡(jiǎn)化布局代碼
          • 對(duì)ConstraintLayout的特性需要掌握熟練,特別是上面這些場(chǎng)景,需要手到擒來(lái)
          • 修改ConstraintLayout時(shí),先理清約束關(guān)系再下手,避免上手就拖組件,導(dǎo)致剪不斷理還亂

          再次重申,ConstraintLayout并不是Android布局的銀彈,合適的場(chǎng)景選擇合適的布局方式,才是最重要的。


          向大家推薦下我的網(wǎng)站?https://xuyisheng.top/??點(diǎn)擊原文一鍵直達(dá)

          專(zhuān)注 Android-Kotlin-Flutter 歡迎大家訪問(wèn)


          瀏覽 73
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  色婷婷aⅴ | 青青草网址 | 国产毛片在线 | 天天cao | 亚洲视频免费观看H |