ConstraintLayout的使用

ConstraintLayout是什么?

ConstraintLayout允許我們只需要一個View層級而無需嵌套多個view,就可以創建一個龐大而又復雜的布局,這和RelativeLayout有點像,里面的子View會根據它們之間的關系來排列。但ConstraintLayout相對于RelativeLayout會更加靈活,使用AS的布局編輯器時,ConstraintLayout會更簡單。

使用AS的布局編輯器來新建ConstraintLayout布局效率是很高的,只需要輕松地拖拽控件就可以實現,我們無需去通過繁瑣地編輯XML布局去實現一個ConstraintLayout布局。

何謂約束

為了確認一個view在ConstraintLayout中的位置,你一定至少要給view添加一個橫向或垂直的約束,每一個約束都代表著這個view相對于其它view、父布局、或者不可見的guideline之間的聯系或者對其關系。每個約束定義了view沿著橫軸和縱軸的位置,所以每個view都必須至少要有一個橫軸或眾軸的約束,但通常情況下會有多個約束。

使用環境

  • Android SDK Version 2.3+ (API Version>= 9)
  • Android Studio 2.3+

如何新建一個帶有ConstraintLayout布局的項目?

  • 依次點擊 Tools > Android > SDK Manager.

  • 點擊SDK Tools

  • 展開Support Repository ,選中ConstraintLayout for Android和 Solver for ConstraintLayout

圖片.png
  • 點擊ok,讓AS去下載相關jar包

  • build.gradle 配置

dependencies {
    compile 'com.android.support.constraint:constraint-layout:1.0.1'
}

ConstraintLayout各種布局約束介紹

  • Relative positioning(相對定位約束)

相對定位約束就是控件的邊被其它控件的邊約束,相對定位約束在ConstraintLayout很常見,可以約束view相對于其它view的位置,你可以這樣在橫軸和縱軸約束你的控件:

1. Horizontal Axis: Left, Right, Start and End sides
2. Vertical Axis: top, bottom sides and text baseline

舉個例子,假如B相對于A,在其右邊

圖片.png

在ConstraintLayout中只需要添加以下代碼就可以實現

<Button android:id="@+id/buttonA" ... />
         <Button android:id="@+id/buttonB" ...
                 app:layout_constraintLeft_toRightOf="@+id/buttonA" />

上面這段代碼的意思就是告訴系統我們想讓按鈕B的左邊被約束在按鈕A的右邊。

其它約束的列表如下:

  • layout_constraintLeft_toLeftOf

  • layout_constraintLeft_toRightOf

  • layout_constraintRight_toLeftOf

  • layout_constraintRight_toRightOf

  • layout_constraintTop_toTopOf

  • layout_constraintTop_toBottomOf

  • layout_constraintBottom_toTopOf

  • layout_constraintBottom_toBottomOf

  • layout_constraintBaseline_toBaselineOf

  • layout_constraintStart_toEndOf

  • layout_constraintStart_toStartOf

  • layout_constraintEnd_toStartOf

  • layout_constraintEnd_toEndOf

這些約束不用刻意去記它,只要明白中間代表控件的約束類型,最后代表約束條件。拿layout_constraintLeft_toLeftOf 來舉例,constraintLeft代表的橫向軸上的左邊約束類型,條件是在相對于某個控件在其左邊。使用了layout_constraintLeft_toLeftOf 的控件,是告訴系統希望其左邊相對于其它控件,在其左邊。

  • Margins

用于設定有約束關系的兩個控件之間的margin值

  • android:layout_marginStart

  • android:layout_marginEnd

  • android:layout_marginLeft

  • android:layout_marginTop

  • android:layout_marginRight

  • android:layout_marginBottom

Margins when connected to a GONE widget

如果一個位置約束的目標控件的visiable為Gone,這種情況下,也可以給它設置margin屬性值。

  • layout_goneMarginStart

  • layout_goneMarginEnd

  • layout_goneMarginLeft

  • layout_goneMarginTop

  • layout_goneMarginRight

  • layout_goneMarginBottom

Centering positioning and bias

設置兩個相反(相對)的約束,可以讓控件居中顯示。例如:同時給控件設置layout_constraintLeft_toLeftOf值為parent和layout_constraintRight_toRightOf的值為parent,那么該控件就水平居中顯示了,豎直居中也同理也是可以實現的。

  <Button
        android:text="Button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button17"
        android:layout_marginStart="16dp"
        android:layout_marginEnd="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        android:layout_marginTop="16dp"
        app:layout_constraintTop_toTopOf="parent" />

圖片.png

Bias

設置兩個相對的約束,可以讓控件居中顯示,也就是偏移50%水平或者垂直顯示。但如果想讓控件偏移30%顯示該怎么辦?通過下面的屬性可以輕易完成:

  • layout_constraintHorizontal_bias

  • layout_constraintVertical_bias

這兩個屬性的值設置的在0~1之間變化,如果想設置水平偏移30%,那么就設置layout_constraintHorizontal_bias 值為0.3,居中顯示則為0.5

圖片.png
  <Button
        android:text="A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button17"
        app:layout_constraintHorizontal_bias="0.3"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"/>
         

注意:別忘記添加layout_constraintLeft_toLeftOf和layout_constraintRight_toRightOf這兩個約束

Dimensions constraints

可以給ConstraintLayout設置一個最小的寬度和高度,但是只有當設置的最小值對應屬性為“WRAP_CONTENT”時才會生效。

  • android:minWidth set the minimum width for the layout

  • android:minHeight set the minimum height for the layout

Widgets dimension constraints

給ConstraintLayout中的控件設置寬(android:layout_width)和高(android:layout_height)有以下三種方式可以實現:

  • 設置固定的尺寸,比如123dp

  • WRAP_CONTENT 自適應尺寸

  • 設置為0dp,想讓控件填充父布局,設置android:layout_width = "0dp"就可以實現了,這和一般的控件就不太一樣。

說明:ConstraintLayout不支持MATCH_PARENT屬性,因為我們可以通過 設置兩個相反的left/right 或 top/bottom約束實現。

圖片.png

Ratio(比例)

我們還可以給控件的寬和高設置一個比例(ratdio)要達到這個效果,至少要把約束控件的寬或者高其中一個設置為0dp,然后再添加layout_constraintDimentionRatio屬性設置(寬:高)的值。

   <Button
        android:text="A"
        android:layout_width="300dp"
        android:layout_height="0dp"
        android:id="@+id/button17"
        app:layout_constraintDimensionRatio="1:1"/>

這個布局中,Button的寬度 = 1 * 300dp = 300dp,而高度是自適應的。
ratdio的寫法:

  • 可以是一個float值,值為寬和高的比例表示的float值 上面的那個比例可以用1來表示。

  • 也可以直接設置比,例如 1:1

同時我們也可以同時設置控件的寬和高都為0dp,然后把ratio可以用"H/W,16:9"來表示,前面如果是H,那么16:9是高:寬;如果前面是W,那么16:9是寬和高的比例。

 <Button android:layout_width="0dp"
                   android:layout_height="0dp"
                   app:layout_constraintDimensionRatio="H,16:9"
                   app:layout_constraintBottom_toBottomOf="parent"
                   app:layout_constraintTop_toTopOf="parent"/>

chains

由多條約束首尾相連組成的一條橫向或者豎直的約束鏈,其中首個元素稱之為chain head。

圖片.png

當我們給chain head設置layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle,整條鏈的狀態將會發生改變。

  • CHAIN_SPREAD -- 元素之間的空間將會均勻分布,這是系統默認的排列方式

  • CHAIN_SPREAD -- 首尾的兩條鏈將不會分配空間,其余內部的鏈將均勻分配空間。

  • CHAIN_PACKED -- 首尾兩條鏈將會分配空間,鏈內部將不會分配空間

  • Weight 通過設置的weight值來分配元素的寬或者高

圖片.png

注意:

(1) layout_constraintHorizontal_chainStyle屬性值是小寫的,文檔里給出的是大寫的。

(2) weight樣式的實現有一個前提,chainStyle必須為默認的spread樣式

(3) 設置Weight樣式時記得把元素中的寬或者設置成0dp

下面是layout_constraintHorizontal_chainStyle為spread_inside樣式代碼:

<?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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <Button
        android:text="A"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button16"
        app:layout_constraintHorizontal_chainStyle="spread_inside"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button17" />


    <Button
        android:text="B"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/button17"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button16"
        app:layout_constraintRight_toLeftOf="@+id/button36"
        android:layout_marginTop="16dp" />

    <Button
        android:text="C"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toRightOf="@+id/button17"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:id="@+id/button36" />


</android.support.constraint.ConstraintLayout>

weight樣式實現

<?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:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">


    <Button
        android:text="A"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="2"
        android:id="@+id/button16"
        app:layout_constraintHorizontal_chainStyle="spread"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/button17" />


    <Button
        android:text="B"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="1"
        android:id="@+id/button17"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintLeft_toRightOf="@+id/button16"
        app:layout_constraintRight_toLeftOf="@+id/button36"
        android:layout_marginTop="16dp" />

    <Button
        android:text="C"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintHorizontal_weight="1"
        android:layout_marginTop="16dp"
        app:layout_constraintLeft_toRightOf="@+id/button17"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        android:id="@+id/button36" />


</android.support.constraint.ConstraintLayout>
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,908評論 6 541
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 99,324評論 3 429
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 178,018評論 0 383
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,675評論 1 317
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 72,417評論 6 412
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,783評論 1 329
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,779評論 3 446
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,960評論 0 290
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 49,522評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 41,267評論 3 358
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 43,471評論 1 374
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 39,009評論 5 363
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,698評論 3 348
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 35,099評論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,386評論 1 294
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 52,204評論 3 398
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 48,436評論 2 378

推薦閱讀更多精彩內容