ConstraintLayout 屬性詳解 和Chain的使用

想看我更多文章:【張旭童的博客】blog.csdn.net/zxt0601
想來gayhub和我gaygayup:【mcxtzhang的Github主頁】github.com/mcxtzhangjavascript

概述

小夥伴們很久不見,我又回來啦。
說實話這篇文章寫的算是比較晚了,距離ConstraintLayout出現至今已經有一年了。
且自AS2.3起建立新的Activity,默認的layout根佈局就是ConstraintLayout
因此再不學習就真的晚了。
我也是正式開始學習的道路,先說一下個人學習過程:html

  • 先閱讀了ConstraintLayout官方文檔Guideline官方文檔
  • 實踐每一個屬性並記下筆記(翻譯)
  • 學習了郭神關於ConstraintLayout可視化操做(拖拖拽拽)的博客,發現博客中對Chain的概念沒有說起
  • 查詢關於Chain以及一些疑點的資料
  • 整理成文
  • 固然中間也遇到了許許多多的問題

本文的順序,大致按照ConstraintLayout官方文檔的順序依次講解(翻譯)屬性和用法,並對疑難點進行額外說明。
關於可視化操做,可參考我寫的動態圖解&實例 ConstraintLayout Chain和郭神博文可視化操做前端

使用前的準備

引入也有坑,無力吐槽。
先放上 截止至20170524,最新版本1.0.1java

compile 'com.android.support.constraint:constraint-layout:1.0.1'

坑是啥?由於我使用的是最新的release版AndroidStudio2.3.2,新建Activity後,自動幫我引入的是1.0.8-alpha版本,
開始我就這麼愉快的學習了,但是當我學習到Chain相關姿式時,特碼的,他竟然報錯。說找不到屬性:android

Error:(10) No resource identifier found for attribute 'layout_constraintHorizontal_chainStyle' in package 'com.mcxtzhang.constraintlayoutdemo'git

ok,那我百度,顯然搜不到的,ok,那我再google,特麼的竟然也搜不到。
震驚,因而機智的我去看源碼,發現我使用的1.0.8-alpha版本的源碼里根本沒有Chain相關屬性的支持,因此我就以爲必定是引入的版本有問題,因而我用google搜索"ConstraintLayout last version",發現誒~官方有說最新版連接以下:
tools.android.com/recent/cons…
按照這個連接提示,最新版是1.0.2,嗯哼,當我換成1.0.2後,發現沒法download....
不知道是網絡問題仍是什麼問題,提示我沒法下載,具體的錯誤記不清了。反正就是沒法獲取到這個版本。
特麼的機智的我又直接去AndroidStudio的Library Dependency裏去搜索,發現竟然搜不到"ConstraintLayout "的庫。再次懵逼。
後來我進行最後的一次嘗試,由於我看google官方上1.0.2版本的上一個版本是1.0.1.因而我修改版本號,sync gradle,竟然成功了。
總結踩坑歷程:github

  • 1 最新Release版AndroidStudio模板自帶的是1.0.8alpha版ConstraintLayout
  • 2 使用Chain相關屬性報錯
  • 3 發現該版本源碼沒有Chain相關屬性
  • 4 官網說的最新版1.0.2 我沒法下載
  • 5 AndroidStudio自帶的Library Dependency搜不到ConstraintLayout
  • 6 修改版本號爲1.0.1 下載

對此,我只能說「驚不驚喜! 意不意外!」
canvas

ConstraintLayout是什麼

先概況一下,它是一個爲了解決佈局嵌套和模仿前端flexible佈局的一個新佈局。網絡

從字面上理解,ConstraintLayout約束佈局
在我理解,這是一個RelativeLayout的升級版。
而當初推出RelativeLayout的目的是爲了在減小多層嵌套佈局
推出ConstraintLayout也是一樣的目的,儘量的使佈局 寬而短,而不是 窄而長。
ConstraintLayout更增強大,不少須要多層嵌套的佈局,使用ConstraintLayout只須要一層便可解決。
它的Chain幾種style方式,和前端的flexbox佈局風格一致,官方文檔中也說了它是flexible方式佈局控件的東西。app

A ConstraintLayout is a ViewGroup which allows you to position and size widgets in a flexible way.

並且搭配可視化的操做,使得佈局也變得更輕鬆。
Google官方推薦全部操做都在"Design"區域搞定,即經過可視化拖拖拽拽生成佈局大體的樣子,而後針對具體屬性、約束 精細修改。
甚至能夠這麼說,你徹底不須要知道ConstraintLayout的具體屬性值分別是什麼,只經過拖拽和鼠標點擊就能夠實現一些佈局。

那麼本文的意義何在呢?

我以爲首先是要知其然知其因此然,那些拖拽點擊生成的代碼屬性究竟是什麼意思?經過本文能夠了解。
另外 雖然大部分操做能夠在「Design」區域完成,可是保不齊的須要你切換至「Text」區域,寫上一兩行屬性代碼,瞭解 這些屬性 老是有益無害的。
並且,有一些屬性是沒法簡單經過拖拽點擊完成的,例如Margins when connected to a GONE widget

剛纔提到RelativeLayout,其實RelativeLayout也是經過約束來佈局子View的呀,
之前RelativeLayout的約束有兩種:

  • 1 子控件和子控件之間的約束(如android:layout_below="@id/title"
  • 2 子控件和父控件的約束(如 android:layout_alignParentTop="true"

如今ConstraintLayout也是相似的,只不過除了以上兩種約束,還多了一種

  • 3 子控件和Guideline的約束

其實關於和Guideline的約束,也能夠理解成約束1,由於Guideline其實就是一個在屏幕上不顯示的View罷了。稍後講到Guideline會帶你們看看它巨簡單的源碼。

下面開始正文,開始屬性的講解

相對定位 (Relative positioning)

這一節的屬性和相對佈局的很像,
值得注意的是參數取值是 ID(@id/button1)表明約束一、3, 或者 字符串"parent" 表明約束2:

  • 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_constraintXXX_toYYYOf,
這裏個人理解, constraintXXX裏的 XXX表明是這個子控件 自身的哪條邊( Left、Right、Top、Bottom、Baseline),
toYYYOf裏的 YYY表明的是和 約束控件哪條邊 發生約束 (取值一樣是 Left、Right、Top、Bottom、Baseline)。
XXXYYY 相反時,表示控件自身的 XXX在約束控件的 YYY的一側,
例如 app:layout_constraintLeft_toRightOf="@id/button1" ,表示的是控件自身的左側在button1的右側。

XXXYYY相同時,表示控件自身的XXX和約束控件的YYY的一側 對齊
例如:app:layout_constraintBottom_toBottomOf="parent",表示控件自身底端和父控件底端對齊。

代碼爲:

<Button
        android:id="@+id/button1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Demo"/>
    <Button
        android:id="@+id/button2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="button2"
        app:layout_constraintLeft_toRightOf="@id/button1"/>
    <Button
        android:id="@+id/button3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginBottom="20dp"
        android:text="button3 跳轉match頁"
        app:layout_constraintBottom_toBottomOf="parent"/>複製代碼

圖示:

Margins

margin和以往的使用一致,注意margin不能爲負值便可。
在上圖中也順便展現了margin的使用。

當約束的widget爲GONE時的Margins

Margins when connected to a GONE widget

舉例,當A控件 約束 在B控件的左邊,B控件GONE了,此時A會額外擁有一個margin的能力,來「補充」B消失的致使的「位移」。
這就是本節的屬性。
這一節的屬性開始我並無理解,後來是經過寫了一些Demo實驗才明白。奈何官方文檔惜字如金,只有一句話,並無Demo展現:

When a position constraint target's visibility is View.GONE, you can also indicates a different margin value to be used using the following attributes:

先看屬性:

  • layout_goneMarginStart
  • layout_goneMarginEnd
  • layout_goneMarginLeft
  • layout_goneMarginTop
  • layout_goneMarginRight
  • layout_goneMarginBottom

在看Demo:

<Button
        android:id="@+id/button4"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:text="button4"
        app:layout_constraintRight_toRightOf="parent"
        />

    <!-- android:layout_marginRight="10dp" 
    配合 app:layout_goneMarginRight="110dp"一塊兒使用,
    在約束的佈局gone時,起用goneMargin,
    可是必定要預先設置對應方向上的margin -->
    <Button
        android:id="@+id/button5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:text="button5"
        app:layout_constraintRight_toLeftOf="@id/button4"
        app:layout_goneMarginRight="110dp"/>複製代碼

此時圖示:


當給button4 隱藏GONE掉之後:
圖示:

會發現Button5紋絲不動,並無收到Button4消失的影響。
這裏咱們再仔細看看button4的android:layout_width="100dp"
而button5的android:layout_marginRight="10dp",app:layout_goneMarginRight="110dp"
110 = 100 +10 , 這是一道小學計算題。

什麼意思?
幾個注意事項:

  • app:layout_goneMarginRight要配合android:layout_marginRight一塊兒使用。
  • 若是隻設置了app:layout_goneMarginRight沒有設置android:layout_marginRight,則無效。(alpha版本的bug,1.0.1版本已經修復)
  • 在約束的佈局gone時,控件自身的marginXXX會被goneMarginXXX替換掉,以本文Demo爲例,本來button4寬度是100,button5的marginRight是10, 加起來是110,若是想讓button4隱藏以後,button5仍然紋絲不動,則須要設置goneMarginRight爲10+100 = 110.

居中定位和傾向(Centering positioning and bias)

居中定位

約束佈局一個有用的地方是它如何處理「不可能」的約束。
好比你定義以下:

<android.support.constraint.ConstraintLayout
    ...
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="button" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>複製代碼

按照咱們第一小節講的屬性值,這個定義的意思是,Button的左邊和父控件的左邊對齊,Button的右邊和父控件的右邊對齊。
但是控件是wrap_content的,它若是不鋪滿父控件要如何能知足這兩個約束呢?
實際效果以下:

控件會居中顯示,由於這兩個約束做用 相似於 水平方向上,有相反的力 去拉控件,最終控件會居中顯示。

傾向(Bias)

搭配bias,能使約束偏向某一邊,默認是0.5,有如下屬性:

  • layout_constraintHorizontal_bias (0最左邊 1最右邊)
  • layout_constraintVertical_bias (0最上邊 1 最底邊)

好比上個Demo,我加入app:layout_constraintHorizontal_bias="0.9" ,則會在水平方向上向右偏移至90%。

<android.support.constraint.ConstraintLayout
    ...
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Button ... app:layout_constraintHorizontal_bias="0.9" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent"/> </android.support.constraint.ConstraintLayout>複製代碼

對可見性的處理(Visibility behavior)

這一節是對前一節goneMargin的補充。
重點是Gone隱藏掉的控件,會被解析成一個點,並忽略margin。

ConstraintLayout能爲View.GoneView特殊處理。
一般,GONE的控件不會被顯示,而且不是佈局自己的一部分(即若是標記爲GONE,則其實際尺寸並不會更改)。
可是在佈局計算方面,GONE的View仍然是其中的一個重要區別:
對於佈局傳遞,它們的維度將被視爲零(基本上它們將被解析爲一個點
若是他們對其餘小部件有約束力,那麼他們仍然會受到尊重,但任何margin都將等於零


注意A的margin也被忽略了。

拿上個Demo改一下,爲A 加上一個android:layout_marginRight="10dp"
爲了使A 隱藏後,B仍能紋絲不動,則B的app:layout_goneMarginRight="120dp"
B goneMarginRight120 = A寬度100 + A marginRight10 +B marginRight10

<Button
        android:id="@+id/button4"
        android:layout_width="100dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:text="button4"
        app:layout_constraintRight_toRightOf="parent"
        />
    <Button android:id="@+id/button5" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginRight="10dp" android:text="button5" app:layout_constraintRight_toLeftOf="@id/button4" app:layout_goneMarginRight="120dp"/>複製代碼

尺寸約束(Dimensions constraints)

ConstraintLayout的最小尺寸 (Minimum dimensions on ConstraintLayout)

能夠爲ConstraintLayout 自身定義最小的尺寸,他會在 ConstraintLayoutWRAP_CONTENT時起做用。
● android:minWidth
● android:minHeight

控件尺寸約束(Widgets dimension constraints)

控件的寬高有三種方式爲其設置:

  • 肯定尺寸
  • WRAP_CONTENT
  • 0dp,就等於MATCH_CONSTRAINT

有些人可能有疑問,爲何不用MATCH_PARENT了。
官方文檔如是說:

MATCH_PARENT is not supported for widgets contained in a ConstraintLayout, though similar behavior can be defined by using MATCH_CONSTRAINT with the corresponding left/right or top/bottom constraints being set to "parent".

意思是MATCH_PARENT再也不被支持了,經過MATCH_CONSTRAINT替代。
咱們寫個Demo看一下三種方式設置的效果吧:

<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
    ...
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/button10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="@+id/button"
        app:layout_constraintRight_toRightOf="@+id/button"
        app:layout_constraintTop_toBottomOf="@+id/button"/>

    <Button
        android:id="@+id/button11"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="@+id/button10"
        app:layout_constraintRight_toRightOf="@+id/button10"
        app:layout_constraintTop_toBottomOf="@+id/button10"/>

</android.support.constraint.ConstraintLayout>複製代碼

效果如圖:


有些人是否是要說,你特麼逗我,不是說好的0dp等於 MATCH_CONSTRAINT,應該是撐滿屏幕的呀,
OK ,把刀放下。讓咱們仔細看這個 MATCH_CONSTRAINT屬性。它match的是約束。
而這裏第三個按鈕的約束是第二個按鈕,因此它的寬度設置爲 MATCH_CONSTRAINT 時, 是和它的約束按鈕,即第二個按鈕同樣寬。
注意,此時,豎直方向上沒有約束,因此不能使用MATCH_CONSTRAINT屬性.

咱們僅僅將第三個按鈕的屬性修改成

app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"複製代碼

則它寬度會撐滿屏幕:

咱們再修改Demo,分別爲後兩個按鈕加上margin:

<android.support.constraint.ConstraintLayout
    ...
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <Button
        android:id="@+id/button"
        android:layout_width="200dp"
        android:layout_height="100dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toTopOf="parent"/>

    <Button
        android:id="@+id/button10"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="@+id/button"
        app:layout_constraintRight_toRightOf="@+id/button"
        app:layout_constraintTop_toBottomOf="@+id/button"/>


    <Button
        android:id="@+id/button12"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="10dp"
        app:layout_constraintLeft_toLeftOf="@id/button10"
        app:layout_constraintRight_toRightOf="@id/button10"
        app:layout_constraintTop_toBottomOf="@id/button10"/>

    <Button
        android:id="@+id/button11"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginRight="10dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/button12"/>

</android.support.constraint.ConstraintLayout>複製代碼

效果如圖:

最後,記住一句話約束要和 0dp 的 方向一致。不然無效

比例(Ratio)

只有一個方向約束:

能夠以比例去定義View的寬高
爲了作到這一點,須要將至少一個約束維度設置爲0dp(即MATCH_CONSTRAINT
並將屬性layout_constraintDimentionRatio設置爲給定的比例。

例如:

<Button
        android:layout_width="200dp"
        android:layout_height="0dp"
        android:text="Ratio"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="2:1"
        app:layout_constraintTop_toTopOf="parent"/>複製代碼

如圖:

比例值有兩種取值:

  • 浮點值,表示寬度和高度之間的比率 (2,0.5)
  • 「width:height」形式的比例 (5:1,1:5)

當約束多於一個(寬高都被約束了)

若是兩個維度均設置爲MATCH_CONSTRAINT(0dp),也可使用比例。 在這種狀況下,系統會使用知足全部約束條件和比率的最大尺寸
若是須要根據一個維度的尺寸去約束另外一個維度的尺寸。
則能夠在比率值的前面添加 W 或者 H 來分別約束寬度或者高度

例如,若是一個尺寸被兩個目標約束(好比寬度爲0,在父容器中居中),可使用 W 或H 來指定哪一個維度被約束。

<Button
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintDimensionRatio="H,2:1"
        app:layout_constraintTop_toTopOf="parent"/>複製代碼

這裏用「H」表示以高度爲約束,高度的最大尺寸就是父控件的高度,「2:1」表示高:寬 = 2 : 1.
則寬度爲高度的一半:

鏈條(Chains)

鏈條在同一個軸上(水平或者垂直)提供一個相似羣組的統一表現。另外一個軸能夠單獨控制。

建立鏈條(Creating a chain)

若是一組小部件經過雙向鏈接(見圖,顯示最小的鏈,帶有兩個小部件),則將其視爲鏈條。

鏈條頭(Chain heads)

鏈條由在鏈的第一個元素(鏈的「頭」)上設置的屬性控制:


頭是水平鏈最左邊的View,或垂直鏈最頂端的View。

鏈的margin(Margins in chains)

若是在鏈接上指定了邊距,則將被考慮在內。
例如

<Button
        android:id="@+id/buttonA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="50dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/buttonB"/>

    <Button android:id="@+id/buttonB" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Button" app:layout_constraintLeft_toRightOf="@+id/buttonA" app:layout_constraintRight_toRightOf="parent"/>複製代碼

經過app:layout_constraintRight_toLeftOf="@+id/buttonB"app:layout_constraintLeft_toRightOf="@+id/buttonA"就創建了鏈條,(我中有你,你中有我)。
而後它們兩個成了一個總體,因此鏈條左邊設置app:layout_constraintLeft_toLeftOf="parent" 使得和父控件左對齊,
右邊設置app:layout_constraintRight_toRightOf="parent"使得和父控件右對齊,
這樣整個鏈條就居中了,最後對左控件設置了margin,至關於整個鏈條左邊有了margin
效果:

鏈條樣式(Chain Style)

當在鏈的第一個元素上設置屬性 layout_constraintHorizontal_chainStylelayout_constraintVertical_chainStyle 時,鏈的行爲將根據指定的樣式(默認爲CHAIN_SPREAD)而更改。
看圖這裏就很像JS裏的flexible有木有。由於ConstraintLayout就是模仿flexible作的。


取值以下:

  • spread - 元素將被展開(默認樣式)
  • 加權鏈 - 在spread模式下,若是某些小部件設置爲MATCH_CONSTRAINT,則它們將拆分可用空間
  • spread_inside - 相似,但鏈的端點將不會擴展
  • packed - 鏈的元素將被打包在一塊兒。 孩子的水平或垂直誤差屬性將影響包裝元素的定位

拿加權鏈舉個例子:

<Button
        android:id="@+id/buttonA"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginLeft="50dp"
        android:text="Button"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/buttonB"/>

    <Button android:id="@+id/buttonB" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintLeft_toRightOf="@+id/buttonA" app:layout_constraintRight_toRightOf="parent"/>複製代碼

加權鏈(Weighted chains)

LinearLayout的weight相似。

鏈的默認行爲是在可用空間中平均分配元素。 若是一個或多個元素使用MATCH_CONSTRAINT,它們將使用剩餘的空白空間(在它們之間相等)。 屬性layout_constraintHorizontal_weightlayout_constraintVertical_weight將決定這些都設置了MATCH_CONSTRAINT的View如何分配空間。 例如,在包含使用MATCH_CONSTRAINT的兩個元素的鏈上,第一個元素使用權重爲2,第二個元素的權重爲1,第一個元素佔用的空間將是第二個元素的兩倍

最後關於鏈條,再給你們看一個關於margin的demo:

<Button
        android:id="@+id/buttonA"
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        android:layout_marginLeft="50dp"
        android:text="Button"
        app:layout_constraintHorizontal_chainStyle="spread"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toLeftOf="@+id/buttonB"/>

    <Button android:id="@+id/buttonB" android:layout_width="0dp" android:layout_height="wrap_content" android:text="Button" app:layout_constraintLeft_toRightOf="@+id/buttonA" app:layout_constraintRight_toRightOf="parent"/>複製代碼


一圖勝千言,能夠看到雖然他們的weight相等,可是margin是被計算在約束裏的,因此左邊的按鈕寬度比右邊的小。


Guideline

Guideline只能用於ConstraintLayout中,是一個工具類,不會被顯示,僅僅用於輔助佈局
它能夠是horizontal或者 vertical的。(例如:android:orientation="vertical"

  • verticalGuideline寬度爲零,高度爲ConstraintLayout的高度
  • horizontalGuideline高度爲零,寬度爲ConstraintLayout的高度

定位Guideline有三種方式:

  • 指定距離左側或頂部的固定距離(layout_constraintGuide_begin
  • 指定距離右側或底部的固定距離(layout_constraintGuide_end
  • 指定在父控件中的寬度或高度的百分比layout_constraintGuide_percent

一個栗子一看便知:

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

    <android.support.constraint.Guideline
        android:id="@+id/guideline"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="vertical"
        app:layout_constraintGuide_begin="100dp"/>

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_marginTop="16dp"
        android:text="Button"
        app:layout_constraintLeft_toLeftOf="@+id/guideline"
        app:layout_constraintTop_toTopOf="parent"/>

</android.support.constraint.ConstraintLayout>複製代碼

預覽:

Guideline源碼:

public class Guideline extends View {
    public Guideline(Context context) {
        super(context);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs) {
        super(context, attrs);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        super.setVisibility(8);
    }
    public Guideline(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) {
        super(context, attrs, defStyleAttr);
        super.setVisibility(8);
    }
    public void setVisibility(int visibility) {
    }
    public void draw(Canvas canvas) {
    }
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        this.setMeasuredDimension(0, 0);
    }
}複製代碼
public static final int GONE = 0x00000008;複製代碼

源碼就這麼點,這貨的源碼和ViewStub有點像啊,能夠看出

  • 它默認是GONE的。8 就是View.GONE的值。
  • 它的public void setVisibility(int visibility)方法被空實現了,因此用戶也沒辦法改變它的可見度。
  • 推導出它必定是GONE的。在屏幕上不可見
  • this.setMeasuredDimension(0, 0);public void draw(Canvas canvas)的空實現,代表這是一個超輕量的View,不可見,沒有寬高,也不繪製任何東西。僅僅做爲咱們的錨點使用。

總結

好久不寫博客了,一是工做太忙了,二也是隨意的寫怕誤人子弟。
這篇文章我寫了整整一天,每一個例子我都邊寫邊跑了一遍,
也看了幾篇別人的文章,有些人簡單的翻譯了官方文檔,可是對文檔中一些沒有舉例, 不那麼好理解的地方也沒有說明,因而便有了此文。
關於可視化操做,建議直接看我寫的動態圖解&實例 ConstraintLayout Chain和郭神博文可視化操做
我以爲ConstraintLayout ,有這幾篇就夠了。

文中代碼地址在個人Demo合集中:
github.com/mcxtzhang/D…

想看我更多文章:【張旭童的博客】blog.csdn.net/zxt0601
想來gayhub和我gaygayup:【mcxtzhang的Github主頁】github.com/mcxtzhang

相關文章
相關標籤/搜索