前言
ConstraintLayout是谷歌2016年I/O大會(huì)發(fā)布的新型的layout布局,當(dāng)然到現(xiàn)在已經(jīng)在很多的APP中大范圍使用了币砂,關(guān)于好處除了官方文檔各大博客也都說(shuō)的很詳細(xì)了,總之我覺(jué)得ConstraintLayout帶來(lái)的最大好處就是ConstraintLayout可以最大化的減少?gòu)?fù)雜布局的層級(jí)嵌套,實(shí)現(xiàn)布局的扁平化,提升頁(yè)面的渲染速度赃绊。
使用
添加依賴(lài)
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
Relative positioning 相對(duì)約束
<Button android:id="@+id/buttonA" ... />
<Button android:id="@+id/buttonB" ...
app:layout_constraintLeft_toRightOf="@+id/buttonA" />
主要屬性如下:
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
這個(gè)屬性相信大家一看就懂更胖,他是以某個(gè)View布局為約束來(lái)控制自己所在的位置的。
具體實(shí)現(xiàn)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatButton
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button1"
app:layout_constraintStart_toStartOf="parent" //起始位置以父布局為約束
app:layout_constraintTop_toTopOf="parent"/> // 頂部以父布局為約束
<android.support.v7.widget.AppCompatButton
android:id="@+id/button2"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button2"
app:layout_constraintStart_toEndOf="@id/button1" // 起始參照以button1 結(jié)束位置為約束
app:layout_constraintTop_toTopOf="parent"/> // 頂部以父布局為約束
<android.support.v7.widget.AppCompatButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button3"
app:layout_constraintStart_toStartOf="parent" //起始位置以父布局為約束
app:layout_constraintTop_toBottomOf="@id/button1"/> // 頂部以button1的底部為約束
<android.support.v7.widget.AppCompatButton
android:id="@+id/button4"
style="@style/Widget.AppCompat.Button.Colored"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button4"
app:layout_constraintStart_toEndOf="@id/button3" //起始位置以button3的結(jié)束位置為約束
app:layout_constraintTop_toBottomOf="@id/button2"/> //頂部以button2的地步為約束
</android.support.constraint.ConstraintLayout>
Margins 外邊距
[圖片上傳失敗...(image-a9f1d2-1545808041237)]
外邊距不用多說(shuō)铃将,和一般的布局使用方法一樣
具體屬性:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
goneMargin 隱藏邊距
這個(gè)屬性很有意思的,使用方法大家一看就明白了哑梳,當(dāng)前View與另一個(gè)View綁定后劲阎,另一個(gè)View的屬性設(shè)置為了Gone,則該屬性會(huì)生效
具體屬性:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
bias 權(quán)重鸠真,占比
在說(shuō)bias這個(gè)屬性之前我們先看下一下如何讓約束的目標(biāo)居中(橫向悯仙、縱向、整體居中)
[圖片上傳失敗...(image-f6ef5a-1545808041237)]
<android.support.constraint.ConstraintLayout ...>
<Button android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent/>
</>
這里我們看到上面的是橫向居中的弧哎,因?yàn)樗膶挾葹閣rap_content是雁比,左右約束來(lái)自于父布局ConstraintLayout,這樣他就能實(shí)現(xiàn)居中了撤嫩。
具體實(shí)現(xiàn)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
//全局居中
<android.support.v7.widget.AppCompatButton
android:id="@+id/button1"
android:layout_width="100dp"
android:layout_height="100dp"
android:text="button1"
app:layout_constraintBottom_toBottomOf="parent" //底部以父布局的底部為約束
app:layout_constraintEnd_toEndOf="parent" //右側(cè)結(jié)束以父布局的右側(cè)為約束
app:layout_constraintStart_toStartOf="parent" //左側(cè)起始以父布局的左側(cè)為約束
app:layout_constraintTop_toTopOf="parent"/> //頂部以父布局的頂部為約束
<android.support.v7.widget.AppCompatButton
android:id="@+id/button2"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="30dp"
android:layout_marginTop="30dp"
android:text="button2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
// 以 button2 為約束的縱向居中
<android.support.v7.widget.AppCompatButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button3"
app:layout_constraintBottom_toBottomOf="@id/button2" //底部以button2的底部為約束
app:layout_constraintStart_toEndOf="@id/button2"
app:layout_constraintTop_toTopOf="@id/button2"/> //頂部以button2的頂部為約束
</android.support.constraint.ConstraintLayout>
居中實(shí)現(xiàn)了偎捎,也很好理解。那我們需要將約束目標(biāo)定位到約束參照物的非中心位置的時(shí)候呢,這時(shí)候我們就可以用到bias了茴她,其實(shí)居中布局的bias默認(rèn)是0.5的寻拂,他的取值范圍推薦0~1之間。bias有橫向和縱向的兩種展現(xiàn)方式丈牢,他們的延伸軌跡也是也是按照View布局的默認(rèn)方式來(lái)的 從左到右和從上到下祭钉。
layout_constraintHorizontal_bias
layout_constraintVertical_bias
具體實(shí)現(xiàn)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatButton
android:id="@+id/button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button"
app:layout_constraintHorizontal_bias="0.3" //距離父布局的左側(cè)30%權(quán)重
app:layout_constraintVertical_bias="0.2" //距離父布局的頂部20%權(quán)重
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
Circular positioning (1.1版本新加的屬性)
這個(gè)還真想不好用什么恰當(dāng)?shù)闹形脑~來(lái)稱(chēng)呼它,我們先來(lái)看下官方的定義吧
You can constrain a widget center relative to another widget center, at an angle and a distance. This allows you to position a widget on a circle (see Fig. 6). The following attributes can be used:
<div>
<img alt="" src="https://developer.android.com/reference/android/support/constraint/resources/images/circle2.png" width="30%"/>
<img alt="" src="https://developer.android.com/reference/android/support/constraint/resources/images/circle1.png" width="30%"/>
</div>
我是這樣理解的己沛,約束目標(biāo)B以A為約束慌核,而約束規(guī)則是以A形成一個(gè)圓,并根據(jù)添加的圓半徑和圓弧來(lái)定位自己的位置申尼。
具體實(shí)現(xiàn)
<?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:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatButton
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button1"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_bias="0.3"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_bias="0.3"
/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Button2"
app:layout_constraintCircle="@id/button1" // 以button1為約束
app:layout_constraintCircleAngle="120" //圓弧以0時(shí)針開(kāi)始順時(shí)針旋轉(zhuǎn)120°
app:layout_constraintCircleRadius="100dp"/> //圓半徑為100dp
</android.support.constraint.ConstraintLayout>
Ratio 比例
Ratio這個(gè)屬性呢垮卓,其實(shí)它的應(yīng)用場(chǎng)景對(duì)于Andrid的屏幕適配很友好,它會(huì)讓View按照一定的比列來(lái)展示給我們师幕。
比如我們的ImageView展示要求按照寬高3:4來(lái)展示粟按,如果我們將寬高按照UI設(shè)計(jì)稿來(lái)寫(xiě)死的話,不是說(shuō)不行霹粥,但是在適配上就很尷尬灭将。Ratio就可以幫助我們解決這個(gè)問(wèn)題,使用Ratio必須要保證View的寬高有一方為0dp,這樣才能按照一定比例進(jìn)行展示后控。
具體實(shí)現(xiàn)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="200dp"
android:layout_height="0dp" //高度為0
android:background="@mipmap/hhh"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="3:4" //寬高比3:4
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
當(dāng)然庙曙,如果兩個(gè)尺寸都為0dp,我們?yōu)榱吮3直攘械脑?可以預(yù)先附加W或H,分別約束寬或高忆蚀。
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@mipmap/hhh"
app:layout_constraintDimensionRatio="H,3:1"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
注:
app:layout_constraintDimensionRatio="H,3:1"和
app:layout_constraintDimensionRatio="W,1:3"這兩個(gè)是一樣的
通過(guò)layout_constraintWidth_percent來(lái)調(diào)整寬度
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@mipmap/hhh"
app:layout_constraintDimensionRatio="W,1:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintWidth_percent="0.5" //寬度占屏幕50%
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
通過(guò)layout_constraintHorizontal_bias來(lái)擺放位置
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<ImageView
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@mipmap/hhh"
app:layout_constraintDimensionRatio="W,1:3"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintWidth_percent="0.5"
app:layout_constraintHorizontal_bias="0.2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
Chains
[圖片上傳失敗...(image-793814-1545808041237)]
chains這個(gè)給我的感覺(jué)像LinearLayout里面的weight屬性矾利,但是比他更為靈活;有點(diǎn)類(lèi)似css里面的FlexBox彈性盒子布局馋袜,Chains必須有兩個(gè)View組成,這兩個(gè)View相互約束舶斧,Chains中的第一個(gè)控件叫做chain head,我們稱(chēng)之為鏈頭吧欣鳖,Chain Style的樣式主要由鏈頭來(lái)控制
Chain Style 屬性樣式
[圖片上傳失敗...(image-2651f7-1545808041237)]
具體實(shí)現(xiàn)
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#82d959"
android:gravity="center"
android:text="chain1"
app:layout_constraintHorizontal_chainStyle="spread" //鏈頭設(shè)置樣式
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tv2"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#b536d8"
android:gravity="center"
android:text="chain2"
app:layout_constraintLeft_toRightOf="@+id/tv1"
app:layout_constraintRight_toLeftOf="@+id/tv3"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#de8f6a"
android:gravity="center"
android:text="chain3"
app:layout_constraintLeft_toRightOf="@+id/tv2"
app:layout_constraintRight_toLeftOf="@+id/tv4"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv4"
android:layout_width="wrap_content"
android:layout_height="50dp"
android:background="#07d2e4"
android:gravity="center"
android:text="chain4"
app:layout_constraintLeft_toRightOf="@+id/tv3"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
通過(guò)layout_constraintHorizontal_weight來(lái)設(shè)置權(quán)重
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv1"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#82d959"
android:gravity="center"
android:text="chain1"
app:layout_constraintHorizontal_weight="1" //設(shè)置權(quán)重
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/tv2"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv2"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#b536d8"
android:gravity="center"
android:text="chain2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/tv1"
app:layout_constraintRight_toLeftOf="@+id/tv3"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv3"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#de8f6a"
android:gravity="center"
android:text="chain3"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/tv2"
app:layout_constraintRight_toLeftOf="@+id/tv4"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv4"
android:layout_width="0dp"
android:layout_height="50dp"
android:background="#07d2e4"
android:gravity="center"
android:text="chain4"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintLeft_toRightOf="@+id/tv3"
app:layout_constraintRight_toRightOf="parent"/>
</android.support.constraint.ConstraintLayout>
GuideLine 基準(zhǔn)線
GuideLine、Barrier茴厉、Group都是是ConstraintLayout的一個(gè)輔助類(lèi)的控件泽台,運(yùn)行時(shí)是看不見(jiàn)的;顧名思義矾缓,GuideLine就是為ConstraintLayout里的子布局提供位置擺放的基準(zhǔn)的怀酷,他有水平和垂直兩種方向android:orientation="horizontal",android:orientation="vertical"
GuideLine有三種定位方式
layout_constraintGuide_begin 距離ConstraintLayout的左側(cè)或者頂部的距離
layout_constraintGuide_end 距離ConstraintLayout的右側(cè)或者底部的距離
layout_constraintGuide_percent 占ConstraintLayout的寬或高的百分比
比如有一下這樣一個(gè)場(chǎng)景嗜闻,用GuideLine就可以妥妥的解決
<?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"
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"
app:layout_constraintGuide_begin="100dp" // 距離左側(cè)100dp
android:orientation="vertical"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/button1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button1"
app:layout_constraintRight_toLeftOf="@id/guideline"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/button2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button2"
app:layout_constraintLeft_toRightOf="@id/guideline"
app:layout_constraintTop_toBottomOf="@id/button1"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/button3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="button3"
app:layout_constraintRight_toLeftOf="@id/guideline"
app:layout_constraintTop_toBottomOf="@id/button2"/>
</android.support.constraint.ConstraintLayout>
Barrier(1.1版本新加的控件)
Barrier是一個(gè)很實(shí)用的輔助類(lèi)控件蜕依,字面意思為邊界的意思,他的作用是限制所引用一組View的邊界,讓這一組View的邊界動(dòng)態(tài)的統(tǒng)一起來(lái);關(guān)于Barrier的介紹非常的詳細(xì)样眠,這里的介紹就遵從該網(wǎng)站的翻譯簡(jiǎn)單的說(shuō)下吧
如上圖所示友瘤,我們創(chuàng)建布局的時(shí)候,有時(shí)候布局里面的控件內(nèi)容是變化的檐束,我們有三個(gè)TextViews: 左邊 textView1 和 textView2 辫秧,右邊 textView3。textView3 以textView1 右側(cè)為約束被丧,這樣似乎看不出什么問(wèn)題盟戏。但是當(dāng)textView2的文本內(nèi)容很長(zhǎng)的時(shí)候就會(huì)出現(xiàn)問(wèn)題了,如下圖:
這個(gè)問(wèn)題很好理解的甥桂,因?yàn)閠extView3是相對(duì)于textView1的柿究。當(dāng)然解決這個(gè)問(wèn)題的方案最常見(jiàn)的方法就是在textView1、textView2外面包一層LinearLayout格嘁。但是現(xiàn)在Barrier可以完美解決這個(gè)問(wèn)題
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="tv1,tv2"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Rxjava"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:text="大王叫我來(lái)巡山"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv1"/>
<android.support.v7.widget.AppCompatTextView
android:id="@+id/tv3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:text="RxJava到底是什么笛求?讓我們直接跳過(guò)官方那種晦澀的追求精確的定義,其實(shí)初學(xué)RxJava只要把握兩點(diǎn):觀察者模式和異步,就基本可以熟練使用RxJava了糕簿。
異步在這里并不需要做太多的解釋?zhuān)驗(yàn)樵诟拍詈褪褂蒙咸饺耄](méi)有太多高深的東西。大概就是你腦子里想能到的那些多線程懂诗,線程切換這些東西蜂嗽。我會(huì)在后面會(huì)講解它的用法。"
app:layout_constraintLeft_toLeftOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
- barrierDirection屬性決定 Barrier 的方向 ,可選擇設(shè)置范圍left殃恒、start植旧、right、end离唐、top病附、 bottom。他是給約束目標(biāo)指定對(duì)齊的方向亥鬓。
start
[圖片上傳失敗...(image-9de867-1545808041237)]
end
[圖片上傳失敗...(image-73e2d0-1545808041237)]
constraint_referenced_ids Barrier指定引用的view的ID完沪,以逗號(hào)隔開(kāi)。
barrierAllowsGoneWidgets:默認(rèn)為true嵌戈,用來(lái)指定barrier是否生效
Group (1.1版本新加的控件)
Group可以幫助你對(duì)一組控件進(jìn)行統(tǒng)一的管理覆积。我們最常見(jiàn)的情況是控制一組控件的visibility。你只需把控件的id引用到Group熟呛,就能同時(shí)對(duì)里面的所有控件進(jìn)行操作宽档。
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
xmlns:app="http://schemas.android.com/apk/res-auto">
<android.support.v7.widget.AppCompatTextView
android:layout_width="wrap_content"
android:id="@+id/tv1"
android:text="text1"
android:layout_height="wrap_content"/>
<android.support.v7.widget.AppCompatTextView
android:layout_width="wrap_content"
android:id="@+id/tv2"
android:text="text2"
app:layout_constraintTop_toBottomOf="@id/tv1"
android:layout_height="wrap_content"/>
<android.support.constraint.Group
android:layout_width="wrap_content"
android:id="@+id/group"
app:constraint_referenced_ids="tv1,tv2"
android:visibility="visible" // 控制tv1,tv2的顯示和隱藏
android:layout_height="wrap_content"/>
</android.support.constraint.ConstraintLayout>
ConstraintSet
我們知道在LinearLayout、RelativeLayout等中庵朝,如果想通過(guò)代碼來(lái)更改布局吗冤,則需要LayoutParams又厉,來(lái)控制控件的大小位置等。但是在ConstraintLayout中官方不建議使用LayoutParams欣孤,官方則推薦使用ConstraintSet來(lái)使用馋没。ConstraintSet不僅可以調(diào)整布局,還可以添加動(dòng)畫(huà)降传。
我們可以通過(guò)以下 3 種方式來(lái)獲取 ConstraintSet:
1. 手動(dòng)創(chuàng)建
c = new ConstraintSet();
c.connect(....);
2. 讀取xml文件
c.clone(context, R.layout.test);
3. 復(fù)制其他ConstraintLayout
c.clone(clayout);
具體實(shí)現(xiàn)方式:
- 替換XML布局
<img alt="" src="https://note.youdao.com/yws/public/resource/7a468e2de3cbce69974f3bef9fd72570/xmlnote/C059ECD8CFB9474EAB8120C6326CEA32/2744" width="40%" />
// Activity
public class ConstraintDemo1Activity extends AppCompatActivity {
ConstraintSet mConstraintSet1 = new ConstraintSet(); // create a Constraint Set
ConstraintSet mConstraintSet2 = new ConstraintSet(); // create a Constraint Set
private ConstraintLayout mConstraintLayout;
private AppCompatImageView mImageView;
boolean mOld = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_constraint_demo1);
initEvent();
}
private void initEvent() {
mConstraintSet2.clone(this, R.layout.activity_constraint_demo2);
mConstraintLayout = findViewById(R.id.root);
mConstraintSet1.clone(mConstraintLayout);
mImageView = findViewById(R.id.imageView);
mImageView.setOnClickListener(v -> {
TransitionManager.beginDelayedTransition(mConstraintLayout);
if (mOld = !mOld) {
mConstraintSet1.applyTo(mConstraintLayout); // set new constraints
} else {
mConstraintSet2.applyTo(mConstraintLayout); // set new constraints
}
});
}
}
// xml
//activity_constraint_demo1
<?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:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintDemo1Activity">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imageView"
android:layout_width="100dp"
android:layout_height="0dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
android:layout_marginTop="8dp"
app:layout_constraintDimensionRatio="3:4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:srcCompat="@mipmap/hhh"/>
</android.support.constraint.ConstraintLayout>
//activity_constraint_demo2
<?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:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintDemo1Activity">
<android.support.v7.widget.AppCompatImageView
android:id="@+id/imageView"
android:layout_width="250dp"
android:layout_height="0dp"
android:layout_marginBottom="8dp"
android:layout_marginEnd="8dp"
android:layout_marginStart="8dp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintDimensionRatio="3:4"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:srcCompat="@mipmap/hhh"/>
</android.support.constraint.ConstraintLayout>
- 完全代碼控制
<img alt="" src="https://note.youdao.com/yws/public/resource/7a468e2de3cbce69974f3bef9fd72570/xmlnote/03AD6025BC9F4A069931EF4D111F62D9/2763" width="40%" />
//Activity
public class ConstraintDemo2Activity extends AppCompatActivity {
private AppCompatButton mBtnOne;
private AppCompatButton mBtnTwo;
private AppCompatButton mBtnThree;
private AppCompatButton mBtnApply;
private ConstraintLayout mRoot;
private ConstraintSet mConstraintSet1 = new ConstraintSet();
private ConstraintSet mConstraintSet2 = new ConstraintSet();
boolean mOld = true;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_constraint2_layout);
initView();
initEevent();
}
private void initView() {
mBtnOne = findViewById(R.id.btn_one);
mBtnTwo = findViewById(R.id.btn_two);
mBtnThree = findViewById(R.id.btn_three);
mBtnApply = findViewById(R.id.btn_apply);
mRoot = findViewById(R.id.root);
}
private void initEevent() {
mConstraintSet1.clone(mRoot);
mConstraintSet2.clone(mRoot);
mBtnApply.setOnClickListener(v->apply());
}
private void apply() {
TransitionManager.beginDelayedTransition(mRoot);
if (mOld = !mOld) {
//默認(rèn)樣式
mConstraintSet2.applyTo(mRoot);
}else {
//清除子View的布局
mConstraintSet1.clear(R.id.btn_one);
mConstraintSet1.clear(R.id.btn_two);
mConstraintSet1.clear(R.id.btn_three);
//重新排列布局
mConstraintSet1.connect(R.id.btn_one, ConstraintSet.LEFT, R.id.root, ConstraintSet.LEFT, 0);
mConstraintSet1.connect(R.id.btn_three, ConstraintSet.RIGHT, R.id.root, ConstraintSet.RIGHT, 0);
mConstraintSet1.connect(R.id.btn_two, ConstraintSet.LEFT, R.id.btn_one, ConstraintSet.RIGHT, 0);
mConstraintSet1.connect(R.id.btn_one, ConstraintSet.RIGHT, R.id.btn_two, ConstraintSet.LEFT, 0);
mConstraintSet1.connect(R.id.btn_two, ConstraintSet.RIGHT, R.id.btn_three, ConstraintSet.LEFT, 0);
mConstraintSet1.connect(R.id.btn_three, ConstraintSet.LEFT, R.id.btn_two, ConstraintSet.RIGHT, 0);
//設(shè)置chains的樣式
mConstraintSet1.createHorizontalChain(R.id.root, ConstraintSet.LEFT,
R.id.root, ConstraintSet.RIGHT,
new int[]{R.id.btn_one,R.id.btn_two,R.id.btn_three}, null, ConstraintWidget.CHAIN_PACKED);
//設(shè)置子View的寬高
mConstraintSet1.constrainWidth(R.id.btn_one,ConstraintSet.WRAP_CONTENT);
mConstraintSet1.constrainWidth(R.id.btn_two,ConstraintSet.WRAP_CONTENT);
mConstraintSet1.constrainWidth(R.id.btn_three,ConstraintSet.WRAP_CONTENT);
mConstraintSet1.constrainHeight(R.id.btn_one,ConstraintSet.WRAP_CONTENT);
mConstraintSet1.constrainHeight(R.id.btn_two,ConstraintSet.WRAP_CONTENT);
mConstraintSet1.constrainHeight(R.id.btn_three,ConstraintSet.WRAP_CONTENT);
//重新載入布局
mConstraintSet1.applyTo(mRoot);
}
}
}
// xml
<?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:id="@+id/root"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".ConstraintDemo2Activity">
<android.support.v7.widget.AppCompatButton
android:id="@+id/btn_one"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="30dp"
android:layout_marginTop="50dp"
android:background="@color/colorAccent"
android:text="button1"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/btn_two"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="40dp"
android:layout_marginTop="20dp"
android:background="@android:color/holo_green_dark"
android:text="button2"
app:layout_constraintStart_toEndOf="@id/btn_one"
app:layout_constraintTop_toBottomOf="@id/btn_one"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/btn_three"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="20dp"
android:background="@android:color/holo_orange_dark"
android:text="button3"
app:layout_constraintStart_toEndOf="@id/btn_one"
app:layout_constraintTop_toBottomOf="@id/btn_two"/>
<android.support.v7.widget.AppCompatButton
android:id="@+id/btn_apply"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginBottom="30dp"
android:text="apply"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"/>
</android.support.constraint.ConstraintLayout>
總結(jié)
本文主要參照官方文檔并加上自己的理解來(lái)的篷朵,在這我們看到ConstraintLayout的強(qiáng)大之處,他可以說(shuō)是veLayout和LinearLayout的集大成者婆排,同時(shí)又簡(jiǎn)化了布局的層層嵌套声旺,大大提升了頁(yè)面的渲染速度。但是官方提供的可拖拽的功能還不是很完美段只,大多情況下需要手動(dòng)調(diào)整腮猖。總之赞枕,ConstraintLayout是現(xiàn)階段的大勢(shì)所趨澈缺。