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
點擊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,在其右邊
在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" />
Bias
設置兩個相對的約束,可以讓控件居中顯示,也就是偏移50%水平或者垂直顯示。但如果想讓控件偏移30%顯示該怎么辦?通過下面的屬性可以輕易完成:
layout_constraintHorizontal_bias
layout_constraintVertical_bias
這兩個屬性的值設置的在0~1之間變化,如果想設置水平偏移30%,那么就設置layout_constraintHorizontal_bias 值為0.3,居中顯示則為0.5
<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約束實現。
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。
當我們給chain head設置layout_constraintHorizontal_chainStyle或layout_constraintVertical_chainStyle,整條鏈的狀態將會發生改變。
CHAIN_SPREAD -- 元素之間的空間將會均勻分布,這是系統默認的排列方式
CHAIN_SPREAD -- 首尾的兩條鏈將不會分配空間,其余內部的鏈將均勻分配空間。
CHAIN_PACKED -- 首尾兩條鏈將會分配空間,鏈內部將不會分配空間
Weight 通過設置的weight值來分配元素的寬或者高
注意:
(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>