前言
ConstraintLayout是谷歌2016年I/O大會發布的新型的layout佈局,當然到現在已經在很多的APP中大範圍使用了,關於好處除了官方文件各大部落格也都說的很詳細了,總之我覺得ConstraintLayout帶來的最大好處就是ConstraintLayout可以最大化的減少複雜佈局的層級巢狀,實現佈局的扁平化,提升頁面的渲染速度。
使用
新增依賴
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
複製程式碼
Relative positioning 相對約束
<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
複製程式碼
這個屬性相信大家一看就懂,他是以某個View佈局為約束來控制自己所在的位置的。
具體實現
<?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 結束位置為約束
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的結束位置為約束
app:layout_constraintTop_toBottomOf="@id/button2"/> //頂部以button2的地步為約束
</android.support.constraint.ConstraintLayout>
複製程式碼
Margins 外邊距
外邊距不用多說,和一般的佈局使用方法一樣
具體屬性:
android:layout_marginStart
android:layout_marginEnd
android:layout_marginLeft
android:layout_marginTop
android:layout_marginRight
android:layout_marginBottom
複製程式碼
goneMargin 隱藏邊距
這個屬性很有意思的,使用方法大家一看就明白了,當前View與另一個View繫結後,另一個View的屬性設定為了Gone,則該屬性會生效
具體屬性:
layout_goneMarginStart
layout_goneMarginEnd
layout_goneMarginLeft
layout_goneMarginTop
layout_goneMarginRight
layout_goneMarginBottom
複製程式碼
bias 權重,佔比
在說bias這個屬性之前我們先看下一下如何讓約束的目標居中(橫向、縱向、整體居中)
<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/>
</>
複製程式碼
這裡我們看到上面的是橫向居中的,因為他的寬度為wrap_content是,左右約束來自於父佈局ConstraintLayout,這樣他就能實現居中了。
具體實現
<?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" //右側結束以父佈局的右側為約束
app:layout_constraintStart_toStartOf="parent" //左側起始以父佈局的左側為約束
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>
複製程式碼
居中實現了,也很好理解。那我們需要將約束目標定位到約束參照物的非中心位置的時候呢,這時候我們就可以用到bias了,其實居中佈局的bias預設是0.5的,他的取值範圍推薦0~1之間。bias有橫向和縱向的兩種展現方式,他們的延伸軌跡也是也是按照View佈局的預設方式來的 從左到右和從上到下。
layout_constraintHorizontal_bias
layout_constraintVertical_bias
複製程式碼
具體實現
<?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" //距離父佈局的左側30%權重
app:layout_constraintVertical_bias="0.2" //距離父佈局的頂部20%權重
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版本新加的屬性)
這個還真想不好用什麼恰當的中文詞來稱呼它,我們先來看下官方的定義吧
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:
複製程式碼
我是這樣理解的,約束目標B以A為約束,而約束規則是以A形成一個圓,並根據新增的圓半徑和圓弧來定位自己的位置。
具體實現
<?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時針開始順時針旋轉120°
app:layout_constraintCircleRadius="100dp"/> //圓半徑為100dp
</android.support.constraint.ConstraintLayout>
複製程式碼
Ratio 比例
Ratio這個屬性呢,其實它的應用場景對於Andrid的螢幕適配很友好,它會讓View按照一定的比列來展示給我們。
比如我們的ImageView展示要求按照寬高3:4來展示,如果我們將寬高按照UI設計稿來寫死的話,不是說不行,但是在適配上就很尷尬。Ratio就可以幫助我們解決這個問題,使用Ratio必須要保證View的寬高有一方為0dp,這樣才能按照一定比例進行展示。
具體實現
<?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>
複製程式碼
當然,如果兩個尺寸都為0dp,我們為了保持比列的話,可以預先附加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"這兩個是一樣的
複製程式碼
通過layout_constraintWidth_percent來調整寬度
<?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>
複製程式碼
通過layout_constraintHorizontal_bias來擺放位置
<?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
chains這個給我的感覺像LinearLayout裡面的weight屬性,但是比他更為靈活;有點類似css裡面的FlexBox彈性盒子佈局,Chains必須有兩個View組成,這兩個View相互約束,Chains中的第一個控制元件叫做chain head,我們稱之為鏈頭吧,Chain Style的樣式主要由鏈頭來控制
Chain Style 屬性樣式
具體實現
<?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" //鏈頭設定樣式
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>
複製程式碼
通過layout_constraintHorizontal_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"
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" //設定權重
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 基準線
GuideLine、Barrier、Group都是是ConstraintLayout的一個輔助類的控制元件,執行時是看不見的;顧名思義,GuideLine就是為ConstraintLayout裡的子佈局提供位置擺放的基準的,他有水平和垂直兩種方向android:orientation="horizontal",android:orientation="vertical"
GuideLine有三種定位方式
- layout_constraintGuide_begin 距離ConstraintLayout的左側或者頂部的距離
- layout_constraintGuide_end 距離ConstraintLayout的右側或者底部的距離
- layout_constraintGuide_percent 佔ConstraintLayout的寬或高的百分比
比如有一下這樣一個場景,用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" // 距離左側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是一個很實用的輔助類控制元件,字面意思為邊界的意思,他的作用是限制所引用一組View的邊界,讓這一組View的邊界動態的統一起來;關於Barrier的介紹非常的詳細,這裡的介紹就遵從該網站的翻譯簡單的說下吧
如上圖所示,我們建立佈局的時候,有時候佈局裡面的控制元件內容是變化的,我們有三個TextViews: 左邊 textView1 和 textView2 ,右邊 textView3。textView3 以textView1 右側為約束,這樣似乎看不出什麼問題。但是當textView2的文字內容很長的時候就會出現問題了,如下圖:
這個問題很好理解的,因為textView3是相對於textView1的。當然解決這個問題的方案最常見的方法就是在textView1、textView2外面包一層LinearLayout。但是現在Barrier可以完美解決這個問題
<?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="大王叫我來巡山"
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到底是什麼?讓我們直接跳過官方那種晦澀的追求精確的定義,其實初學RxJava只要把握兩點:觀察者模式和非同步,就基本可以熟練使用RxJava了。
非同步在這裡並不需要做太多的解釋,因為在概念和使用上,並沒有太多高深的東西。大概就是你腦子裡想能到的那些多執行緒,執行緒切換這些東西。我會在後面會講解它的用法。"
app:layout_constraintLeft_toLeftOf="@id/barrier"
app:layout_constraintTop_toTopOf="parent"/>
</android.support.constraint.ConstraintLayout>
複製程式碼
- barrierDirection屬性決定 Barrier 的方向 ,可選擇設定範圍left、start、right、end、top、 bottom。他是給約束目標指定對齊的方向。
start
end
-
constraint_referenced_ids Barrier指定引用的view的ID,以逗號隔開。
-
barrierAllowsGoneWidgets:預設為true,用來指定barrier是否生效
Group (1.1版本新加的控制元件)
Group可以幫助你對一組控制元件進行統一的管理。我們最常見的情況是控制一組控制元件的visibility。你只需把控制元件的id引用到Group,就能同時對裡面的所有控制元件進行操作。
<?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等中,如果想通過程式碼來更改佈局,則需要LayoutParams,來控制控制元件的大小位置等。但是在ConstraintLayout中官方不建議使用LayoutParams,官方則推薦使用ConstraintSet來使用。ConstraintSet不僅可以調整佈局,還可以新增動畫。 我們可以通過以下 3 種方式來獲取 ConstraintSet:
- 手動建立
c = new ConstraintSet();
c.connect(....);
複製程式碼
- 讀取xml檔案
c.clone(context, R.layout.test);
複製程式碼
- 複製其他ConstraintLayout
c.clone(clayout);
複製程式碼
具體實現方式:
- 替換XML佈局
// 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>
複製程式碼
- 完全程式碼控制
//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) {
//預設樣式
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);
//設定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);
//設定子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>
複製程式碼
總結
本文主要參照官方文件並加上自己的理解來的,在這我們看到ConstraintLayout的強大之處,他可以說是RelativeLayout和LinearLayout的集大成者,同時又簡化了佈局的層層巢狀,大大提升了頁面的渲染速度。但是官方提供的可拖拽的功能還不是很完美,大多情況下需要手動調整。總之,ConstraintLayout是現階段的大勢所趨。