1. 程式人生 > >ConstraintLayout 屬性詳解 和Chain的使用

ConstraintLayout 屬性詳解 和Chain的使用

概述

小夥伴們好久不見,我又回來啦。 
說實話這篇文章寫的算是比較晚了,距離ConstraintLayout出現至今已經有一年了。 
且自AS2.3起建立新的Activity,預設的layout根佈局就是ConstraintLayout。 
所以再不學習就真的晚了。 
我也是正式開始學習的道路,先說一下我的學習過程: 
* 先閱讀了ConstraintLayout官方文件Guideline官方文件 
* 實踐每個屬性並記下筆記(翻譯) 
* 學習了郭神關於ConstraintLayout視覺化操作(拖拖拽拽)的部落格,發現部落格中對Chain

的概念沒有提及 
* 查詢關於Chain以及一些疑點的資料 
* 整理成文 
* 當然中間也遇到了許許多多的問題

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

使用前的準備

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

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

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

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

ok,那我百度,顯然搜不到的,ok,那我再google,特麼的居然也搜不到。 
震驚,於是機智的我去看原始碼,發現我使用的1.0.8-alpha

版本的原始碼里根本沒有Chain相關屬性的支援,所以我就覺得一定是引入的版本有問題,於是我用google搜尋”ConstraintLayout last version”,發現誒~官方有說最新版連結如下: 
http://tools.android.com/recent/constraintlayout102isnowavailable 
按照這個連結提示,最新版是1.0.2,嗯哼,當我換成1.0.2後,發現無法download…. 
不知道是網路問題還是什麼問題,提示我無法下載,具體的錯誤記不清了。反正就是無法獲取到這個版本。 
特麼的機智的我又直接去AndroidStudio的Library Dependency裡去搜索,發現居然搜不到“ConstraintLayout “的庫。再次懵逼。 
後來我進行最後的一次嘗試,因為我看google官方上1.0.2版本的上一個版本是1.0.1.於是我修改版本號,sync gradle,居然成功了。 
總結踩坑歷程: 
* 1 最新Release版AndroidStudio模板自帶的是1.0.8alpha版ConstraintLayout 
* 2 使用Chain相關屬性報錯 
* 3 發現該版本原始碼沒有Chain相關屬性 
* 4 官網說的最新版1.0.2 我無法下載 
* 5 AndroidStudio自帶的Library Dependency搜不到ConstraintLayout 
* 6 修改版本號為1.0.1 下載

對此,我只能說“驚不驚喜! 意不意外!” 

ConstraintLayout是什麼

先概況一下,它是一個為了解決佈局巢狀和模仿前端flexible佈局的一個新佈局。

從字面上理解,ConstraintLayout約束佈局。 
在我理解,這是一個RelativeLayout的升級版。 
而當初推出RelativeLayout的目的是為了在減少多層巢狀佈局, 
推出ConstraintLayout也是同樣的目的,儘可能的使佈局 寬而短,而不是 窄而長。 
ConstraintLayout更加強大,很多需要多層巢狀的佈局,使用ConstraintLayout只需要一層即可解決。 
它的Chain幾種style方式,和前端的flexbox佈局風格一致,官方文件中也說了它是flexible方式佈局控制元件的東西。

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)代表約束1、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"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

圖示:

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"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20

此時圖示:

 
當給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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

按照我們第一小節講的屬性值,這個定義的意思是,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>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10

對可見性的處理(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"/>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16

尺寸約束(Dimensions constraints)

相關推薦

ConstraintLayout 屬性 Chain的使用

概述 小夥伴們好久不見,我又回來啦。 說實話這篇文章寫的算是比較晚了,距離ConstraintLayout出現至今已經有一年了。 且自AS2.3起建立新的Activity,預設的layout根佈局就是ConstraintLayout。 所以再不學習就真的晚了。&nbs

ExtJS Combobox 屬性預設值選中

                var store = new Ext.data.SimpleStore({  

HTML embed標簽使用方法屬性

利用 是否 parent als ase sig 默認 eve sel 一、基本語法 代碼如下: embed src=url 說明:embed可以用來插入各種多媒體,格式可以是 Midi、Wav、AIFF、AU、MP3等等,Netscape及新版的IE 都支持。url為

【CSS3 transform屬性過渡屬性

eight tex over doctype ati ext 註意 skew 簡寫 CSS3transform屬性詳解 transform字面上就是變形,改變的意思。 在CSS3中transform主要包括以下幾種:旋轉rotate、扭曲skew、縮放scale和移動tra

HikariCP的基本使用屬性

一、主要配置 1、dataSourceClassName 這是DataSourceJDBC驅動程式提供的類的名稱。請查閱您的特定JDBC驅動程式的文件以獲取此類名稱,或參閱下表。注XA資料來源不受支援。XA需要像bitronix這樣的真正的事務管理器 。請注意,如果您正在使用jdbcUrl“舊式

HTML embed標籤使用方法屬性

一、基本語法   程式碼如下:   embed src=url   說明:embed可以用來插入各種多媒體,格式可以是 Midi、Wav、AIFF、AU、MP3等等,Netscape及新版的IE 都支援。url為音訊或視訊檔案及其路徑,可以是相對路徑或絕對路徑。   示例:

html5的input型別所有屬性

<input type="text">:如果一個input沒有type屬性,那麼它會是預設type="text"。沒有什麼特別的,就是允許輸入文字,簡單明瞭。<input type="password">:顧名思義,在使用者輸入密碼的時候建議使用這個屬性而非text,使用了這個屬性,使

Android中Activity四種啟動模式taskAffinity屬性

在android應用開發中,打造良好的使用者體驗是非常重要的。而在使用者體驗中,介面的引導和跳轉是值得深入研究的重要內容。在開發中,與介面跳轉聯絡比較緊密的概念是Task(任務)和Back Stack(回退棧)。activity的啟動模式會影響Task和Back Stack

Android 總結:Manifest檔案中,applicationactivity標籤屬性

一、application 標籤屬性 < application /> :應用的宣告。 這個元素包含了子元素,這些子元素聲明瞭應用的元件,元素的屬性將會影響應用下的所有元件。

Spring JPA註解Column屬性

fault efault htm lan oracle runt arch public cal 該註解的定義如下: @Target({METHOD, FIELD}) @Retention(RUNTIME) public @interface Column { String

Andoid自定義View的OnMeasure自定義屬性

一,OnMeasure詳解 Android開發中偶爾會用到自定義View,一般情況下,自定義View都需要繼承View類的onMeasure方法,那麼,為什麼要繼承onMeasure()函式呢?什麼情況下要繼承onMeasure()?系統預設的onMeasure()函式行為

Android activity棧、啟動模式intent flag屬性

一、Activity棧的概念        1.每個app應用程式啟動的activity都會儲存在一個單獨的棧裡面。        2.有可能某個activity發生棧轉移。二、acitivity的

Spinner的使用屬性

//測量spinner的高度,方便設定偏移量 int w = View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED); int h = View.MeasureSpec.makeMeasureSpec(0,

css中float屬性position屬性

CSS float 屬性 定義和用法float 屬性定義元素在哪個方向浮動。以往這個屬性總應用於影象,使文字圍繞在影象周圍,不過在 CSS 中,任何元素都可以浮動。浮動元素會生成一個塊級框,而不論它本身是何種元素。 如果浮動非替換元素,則要指定一個明確的寬度;否則,它們會

cookie屬性

ssi 頂級 技術 sources 讀取 超時 logs 通過 html cookie屬性詳解 在chrome控制臺中的resources選項卡中可以看到cookie的信息。 一個域名下面可能存在著很多個cookie對象。 name字段為一個cookie的名稱。

SVN trunk(主線) branch(分支) tag(標記) 用法詳細操作步驟

trac load mar span 必須 最可 objc copy 右鍵 原文地址:http://blog.csdn.net/vbirdbest/article/details/51122637 使用場景: 假如你的項目(這裏指的是手機客戶端項目)的某個版本(例如1.0

Storm容錯機制Acker實戰案例

storm acker 失敗重發 可靠性Storm中有個特殊的Executor叫acker,他們負責跟蹤spout發出的每一個Tuple的Tuple樹。當acker發現一個Tuple樹已經處理完成了,它會告訴框架回調Spout的ack(),否則回調Spout的fail()。Acker的跟蹤算法是Storm的主

hibernate中inverse屬性

values 性能 update 關聯 維護 value str true 詳解 術語”inverse”直譯為”反轉”。在Hibernate中,inverse屬性指定了關聯關系中的方向。關聯關系中,inverse=“false”的為主動方,由主動方維護關聯關系。在一對多關聯

hibernate中 cascade屬性

-m hibernate 發現 執行效率 pda 不一定 () 程序執行效率 刪除 配置關聯時,我們考慮兩點:程序執行效率和實際業務需要,前面的例子中無論是單向的關聯還是雙向的關聯,我們都要分別對實體類使用session.save()才能將數據保存至數據庫。問題:如果

JS中的showModelDialog實例

cti 信息 創建 字符 非模態窗口 tle cin dialog ima 1.<a href="#" onclick="SeePic(‘${list.PATH}‘)"><font color="blue">預覽</font></a