前言
約束布局ConstraintLayout作為Google官方推薦的layout布局文件黑界,是一個和線性布局LinearLayout馍刮,相對布局Relativelayout相似的ViewGroup己莺。
約束布局的出現(xiàn)主要是為了能夠讓布局的設計更加的扁平化,優(yōu)化布局嵌套問題,能夠更加靈活的調整和控制其中的子View隆敢。
約束布局支持API 9以上的Android系統(tǒng)上使用驯耻。
一亲族、包引入
使用ConstraintLayout需要引入對應的包,在build.gradle
文件中引入如下內容:
implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
二可缚、基本使用
約束布局已經支持非常多的功能孽水,主要包括如下幾個部分:
- 相對定位
- 角度定位
- 可見性行為
- 尺寸限制
- 鏈條
- 虛擬化助手對象
- 優(yōu)化器
下面我們將會對上述內容進行逐一講解。
1. 相對定位
相對定位是用來控制子View在ConstraintLayout內部的位置關系城看,它類似于相對布局相對布局Relativelayout女气,能夠以一個View為起點,逐步的定位其他子View的相對位置關系测柠,它包含的主要設置屬性主要包括上下左右四個方面炼鞠,屬性名稱如下:
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的方向邊緣轰胁,后一個方向是參照View的方向邊緣谒主,以layout_constraintBottom_toTopOf為例,你設置的是當前View的底部(bottom)在參照View的頂部(top)赃阀。
上面屬性上包括一個
layout_constraintBaseline_toBaselineOf
,這個指的是中心基準線霎肯,可以使得兩個并排的View的中心基準線在同一水平上,基準線如下圖:
居中定位
如果當你設置的當前控件起始點分別參照兩個View而你當前的控件大小不能夠完全填充兩個參考控件間距大小的情況下,當前設置的控件會被參考View雙向拉伸的效果观游,從而使你當前的控件有居中效果搂捧,示例如下:
我們設置當前button的left和right指向parent,
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
實際效果如下:
偏向定位
如果需要實現(xiàn)偏向效果懂缕,讓當前的控件不再居中而是更加偏向左右 允跑,可以通過額外定義bias
屬性來實現(xiàn)。這一屬性用來設置左側和上方的百分比數(shù)值搪柑,數(shù)值越小聋丝,則當前控件會更加靠近左側或者上方,如果不設置居中的情況下默認是0.5工碾。
bias能使約束偏向某一邊弱睦,默認是0.5
layout_constraintVertical_bias //縱向(0:最上,1:最下)
layout_constraintHorizontal_bias//橫向(0:最左渊额,1:最右)
舉例來說每篷,如果我們想要更加偏向左側
30%,我們就可以設置
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintHorizontal_bias="0.3"
效果如下:
2. 角度定位
除了上述的基本相對定位之外端圈,約束布局還支持角度相對定位焦读,具體方向是以Y軸正半軸為旋轉起始線,順時針旋轉計算角度舱权,示例圖如下:
其中角度定位的主要參數(shù)主要包括三項:定位原點View矗晃,旋轉角度,距離宴倍,分別通過下面三項進行處理:
<!--定位原點View-->
app:layout_constraintCircle="@id/tv_testA"
<!--旋轉角度-->
app:layout_constraintCircleAngle="120"
<!--距離-->
app:layout_constraintCircleRadius="120dp"
3. 可見性行為
當約束布局設置為Gone隱藏當前的控件時张症,當前的控件被解析成一個點,對于其他的控件的約束依然存在鸵贬,但是被隱藏的View本身設置margin會被忽略俗他,具體示例如下:
當View A被設置為不可見時,其對于View B的約束依然存在阔逼,但是View A本身的左邊距會同時也隱藏掉兆衅。
goneMargin
當位置約束目標的可見性為View.GONE
時,可以使用goneMargin
屬性設置不同的邊距值嗜浮。
如上圖羡亩,如果設置View B的app:layout_goneMarginLeft="10dp"
,則當View A設置為View.GONE
時,View B距離左側邊距則為10dp危融。
4. 尺寸限制
———— 大小約束
- 當約束布局的尺寸大小設置為
wrap_content
時畏铆,可以設置其最大大小和最小大小,設置參數(shù)如下:
android:minWidth 設置布局的最小寬度
android:minHeight 設置布局的最小高度
android:maxWidth 設置布局的最大寬度
android:maxHeight 設置布局的最大高度
- 使用0dp吉殃,等同** MATCH_CONSTRAINT**辞居,默認行為是使得結果尺寸占用所有的可用空間楷怒,可替代
match_parent
。
百分比維度
尺寸設置為MATCH_CONSTRAINT時可以采用百分比設置瓦灶,屬性如下:
app:layout_constraintWidth_default="percent"
app:layout_constraintHeight_default="percent"
然后將layout_constraintWidth_percent
和layout_constraintHeight_percent
屬性設置為 0 到 1 之間的值用來制定當前控件的百分比鸠删。
示例如下,我們設置當前控件的寬度百分比為0.33倚搬,高度百分比為0.5,代碼如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
tools:context=".constraintlayout.TestConstraintLayoutActivity">
<TextView
android:id="@+id/tv_testA"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/black"
android:padding="10dp"
android:text="test text"
app:layout_constraintVertical_bias="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_default="percent"
app:layout_constraintHeight_percent="0.5"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintWidth_default="percent"
app:layout_constraintWidth_percent="0.33" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
寬高比設置
當寬或者高至少一個尺寸設置為0dp時乾蛤,可以通過屬性app:layout_constraintDimensionRatio="m:n"
來設置當前控件的寬高比.
屬性默認中m為寬度每界,n為高度。你也可以指定m的為高度或者寬度家卖,需要在添加H或者W眨层。如:
app:layout_constraintDimensionRatio="H,2:3"指的是 高:寬=2:3
app:layout_constraintDimensionRatio="W,2:3"指的是 寬:高=2:3
示例效果如下:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.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"
tools:context=".constraintlayout.TestConstraintLayoutActivity">
<TextView
android:id="@+id/tv_testA"
android:layout_width="0dp"
android:layout_height="0dp"
android:background="@color/black"
android:padding="10dp"
android:layout_marginTop="@dimen/dp_52"
android:text="test text"
app:layout_constraintDimensionRatio="1:2"
app:layout_constraintVertical_bias="0"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintHeight_default="percent"
app:layout_constraintHeight_percent="0.2"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
三、鏈條
鏈條也是約束布局里的一個組行為用法上荡,可以在一個軸上對鏈條組做操作趴樱。
如下圖:
當一組部件通過雙向連接連在一起,則他們可以被視為一條鏈酪捡,其中第一個元素被稱為鏈頭叁征。代碼如下:
<TextView
android:id="@+id/TextView1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/TextView2" />
<TextView
android:id="@+id/TextView2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/TextView1"
app:layout_constraintRight_toLeftOf="@+id/TextView3"
app:layout_constraintRight_toRightOf="parent" />
<TextView
android:id="@+id/TextView3"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:layout_constraintLeft_toRightOf="@+id/TextView2"
app:layout_constraintRight_toRightOf="parent" />
設置好鏈頭之后,我們可以在鏈頭的地方添加屬性已調整整個鏈條的樣式逛薇,一共有三種樣式:
- CHAIN_SPREAD-- 元素將被展開(默認樣式)
加權鏈 - 在CHAIN_SPREAD模式下捺疼,如果某些小部件設置為MATCH_CONSTRAINT,它們將分割可用空間永罚,使用
layout_constraintHorizontal_weight
和layout_constraintVertical_weight
來分別控制每個元素的權重啤呼。
- CHAIN_SPREAD_INSIDE-- 類似,但鏈的端點不會散開
- CHAIN_PACKED-- 鏈的元素將被打包在一起呢袱。子元素的水平或垂直偏差屬性將影響打包元素的定位
示例效果如下:
三官扣、輔助工具
1. Barrier
Barrier可以為我們設置一道分界線線以便我們調整布局。
例如我們有3個控件羞福,其中testB在testA的下方惕蹄,testC在A和B的右方,如果此時A和B的長度不是固定的治专,則此時C的約束依賴無論是A還是B都不正確焊唬,有可能造成遮擋。
使用Barrier可以解決這一問題看靠。Barrier可以生成一道以A和B的右側為基準的分界線赶促,這樣C約束依賴于這道分界線即可,示例代碼如下:
<androidx.constraintlayout.widget.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"
tools:context=".constraintlayout.TestConstraintLayoutActivity">
<TextView
android:id="@+id/tv_testA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_52"
android:background="@color/colorAccent"
android:padding="10dp"
android:text="testA"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<TextView
android:id="@+id/tv_testB"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="@dimen/dp_52"
android:background="@color/colorAccent"
android:paddingHorizontal="@dimen/dp_30"
android:paddingVertical="@dimen/dp_10"
android:text="testB"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_testA" />
<androidx.constraintlayout.widget.Barrier
android:id="@+id/barrier1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:barrierDirection="right"
app:constraint_referenced_ids="tv_testA,tv_testB" />
<TextView
android:id="@+id/tv_testC"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginLeft="@dimen/dp_20"
android:layout_marginTop="@dimen/dp_24"
android:background="@color/colorAccent"
android:padding="10dp"
android:text="testC"
app:layout_constraintLeft_toRightOf="@id/barrier1"
app:layout_constraintTop_toTopOf="@id/tv_testA" />
</androidx.constraintlayout.widget.ConstraintLayout>
app:barrierDirection為屏障所在的位置,可以分別設置上下左右等方向挟炬。
app:constraint_referenced_ids為屏障引用的控件鸥滨,可設置多個(用“,”隔開)
效果:
分界線并不會真實顯示嗦哆,只用來做約束依賴。
2. Group
Group可以把多個控件歸為一組婿滓,方便對當前組的控件統(tǒng)計的進行隱藏或者顯示老速,其用法和barrrier相似,都是設置constraint_referenced_ids
屬性凸主,示例如下,把tv_testA
和tv_testB
一起隱藏:
<androidx.constraintlayout.widget.Group
android:visibility="gone"
app:constraint_referenced_ids="tv_testB,tv_testA"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>