ConstraintLayout最新的版本是1.1.3,這是一個很優(yōu)秀的布局栽连,幾乎可以實現(xiàn)用一級布局翩伪,就能實現(xiàn)復(fù)雜的頁面。
接下來我們深入淺出的來學(xué)習(xí)一下這個牛逼轟轟的控件吧眉尸。
常用布局
這邊的布局有點類似RelativeLayout域蜗,但ConstraintLayout本身就比RelativeLayout強大。
//兩個控件的左邊對齊
layout_constraintLeft_toLeftOf
//當(dāng)前控件的左邊與目標控件的右邊對齊噪猾,即當(dāng)前控件在目標控件的右邊
layout_constraintLeft_toRightOf
//當(dāng)前控件的右邊與目標控件的左邊對齊霉祸,即當(dāng)前控件在目標控件的左邊
layout_constraintRight_toLeftOf
//兩個控件的右邊對齊
layout_constraintRight_toRightOf
//兩個控件的上面對齊
layout_constraintTop_toTopOf
//當(dāng)前控件的頂部與目標控件的底部對齊,即當(dāng)前控件在目標控件的下面
layout_constraintTop_toBottomOf
//當(dāng)前控件的底部與目標控件的頂部對齊袱蜡,即當(dāng)前控件在目標控件的上面
layout_constraintBottom_toTopOf
//兩個控件的下面對齊
layout_constraintBottom_toBottomOf
//baseline對齊丝蹭,常用于和EditText 對齊
layout_constraintBaseline_toBaselineOf
一個簡單的例子
<?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:id="@+id/constraintLayout"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:padding="10dp">
<TextView
android:id="@+id/tv_common_layout_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="常用布局"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btn_e"
android:layout_height="wrap_content"
android:layout_marginTop="50dp"
android:layout_width="wrap_content"
android:text="E"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_common_layout_label"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="A"
app:layout_constraintBottom_toTopOf="@id/btn_e"
app:layout_constraintRight_toLeftOf="@id/btn_e"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="B"
app:layout_constraintBottom_toTopOf="@id/btn_e"
app:layout_constraintLeft_toRightOf="@id/btn_e"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="C"
app:layout_constraintRight_toLeftOf="@id/btn_e"
app:layout_constraintTop_toBottomOf="@id/btn_e"/>
<Button
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="D"
app:layout_constraintLeft_toRightOf="@id/btn_e"
app:layout_constraintTop_toBottomOf="@id/btn_e"/>
</android.support.constraint.ConstraintLayout>
Chain(鏈)
顧名思義,就是把幾個控件鏈在一起坪蚁,以達到可以控制布局的效果奔穿,這個效果也是很常用的。
常用屬性:
layout_constraintHorizontal_chainStyle
layout_constraintVertical_chainStyle
上述兩個屬性只能在鏈的第一個控件上使用敏晤,在之后的控件使用無效贱田。
這兩個屬性的值有三個:spread_inside,spread嘴脾,packed
看一下官方提供的說明圖:
Packed Chain with Bias是packed屬性加layout_constraintHorizontal_bias屬性
Weighted Chain的用法與之前LinearLayout中的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:id="@+id/constraintLayout"
android:layout_height="match_parent"
android:layout_width="match_parent">
<TextView
android:id="@+id/tv_chain_style_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="Chain"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<RadioGroup
android:id="@+id/rg_chain_group"
android:layout_height="wrap_content"
android:layout_marginLeft="10dp"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:orientation="horizontal"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_chain_style_label">
<RadioButton
android:checked="true"
android:id="@+id/rb_spread_inside"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="spread_inside"/>
<RadioButton
android:id="@+id/rb_spread"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="spread"/>
<RadioButton
android:id="@+id/rb_pack"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="pack"/>
</RadioGroup>
<Button
android:id="@+id/btn_fgh_toggle"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="FGH批量隱藏"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/rg_chain_group"/>
<android.support.constraint.Group
android:id="@+id/group_btns"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:constraint_referenced_ids="btn_f,btn_g,btn_h"/>
<Button
android:id="@+id/btn_f"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="F"
app:layout_constraintHorizontal_chainStyle="spread_inside"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_g"
app:layout_constraintTop_toBottomOf="@id/btn_fgh_toggle"/>
<Button
android:id="@+id/btn_g"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="G"
app:layout_constraintLeft_toRightOf="@id/btn_f"
app:layout_constraintRight_toLeftOf="@+id/btn_h"
app:layout_constraintTop_toTopOf="@id/btn_f"/>
<Button
android:id="@+id/btn_h"
android:layout_height="wrap_content"
android:layout_width="0dp"
android:text="H"
app:layout_constraintLeft_toRightOf="@id/btn_g"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/btn_g"/>
</android.support.constraint.ConstraintLayout>
class ChainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.act_chain_style)
rg_chain_group.setOnCheckedChangeListener { _, checkedId ->
constraintLayout.getViewWidget(btn_f).horizontalChainStyle = when (checkedId) {
R.id.rb_spread_inside -> ConstraintLayout.LayoutParams.CHAIN_SPREAD_INSIDE
R.id.rb_spread -> ConstraintLayout.LayoutParams.CHAIN_SPREAD
R.id.rb_pack -> ConstraintLayout.LayoutParams.CHAIN_PACKED
else -> ConstraintLayout.LayoutParams.CHAIN_PACKED
}
constraintLayout.requestLayout()
}
btn_fgh_toggle.setOnClickListener {
if (group_btns.visibility == View.VISIBLE) {
group_btns.visibility = View.GONE
btn_fgh_toggle.text = "fgh批量顯示"
} else {
group_btns.visibility = View.VISIBLE
btn_fgh_toggle.text = "fgh批量隱藏"
}
}
}
}
這里還穿插了一個Group的用法
Group
顧名思義就是把幾個View分成一組,可以統(tǒng)一對其顯隱藏進行控制耗拓,好處就是終于不用再寫一堆的布局顯隱藏拇颅,也不會容易出錯啦。
因為比較簡單乔询,所以也不細說了蔬蕊。
Barrier,屏障猜扮,障礙
這是一個控件,可以使用constraint_referenced_ids來引用多個控件监婶,從而可以得到這組控件的最左邊/最頂部/最右邊/最底部了旅赢。
終于我們做某些要填寫信息的布局時,可以不用TableLayout惑惶,也可以不用去計算哪個標簽長度最長煮盼,估算出一個不太靠譜的長度。
常用的屬性:
//指定方向带污,不可以設(shè)置多個方向鱼冀,如果需要多個方向报破,則需要設(shè)置多個Barrier
barrierDirection
//關(guān)聯(lián)id
constraint_referenced_ids
舉個栗子:
<?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_height="match_parent"
android:layout_width="match_parent"
android:padding="10dp"
tools:context=".MainActivity">
<android.support.constraint.Barrier
android:id="@+id/barrier"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:barrierDirection="end"
app:constraint_referenced_ids="tv_age_label,tv_name_label"/>
<TextView
android:id="@+id/tv_name_label"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:padding="10dp"
android:text="姓名:"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<EditText
android:hint="請輸入姓名"
android:id="@+id/edt_name"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constrainedWidth="true"
app:layout_constraintBaseline_toBaselineOf="@id/tv_name_label"
app:layout_constraintLeft_toRightOf="@+id/barrier"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_name_label"/>
<TextView
android:id="@+id/tv_age_label"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:padding="10dp"
android:text="出生時間:"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toBottomOf="@id/edt_name"/>
<EditText
android:hint="請輸入出生日期"
android:layout_height="wrap_content"
android:layout_width="0dp"
app:layout_constraintBaseline_toBaselineOf="@id/tv_age_label"
app:layout_constraintLeft_toRightOf="@+id/barrier"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="@id/tv_age_label"/>
</android.support.constraint.ConstraintLayout>
圓形定位
這個就有點吊了,控件A可以在控件B周圍的任何位置充易。
常用的場景一般就是設(shè)置小紅點了盹靴,未讀數(shù)之類的。
使用屬性有三個
//圓形定位的目標控件瑞妇,在這個屬性設(shè)置目標的id
layout_constraintCircle
//圓形定位的角度
layout_constraintCircleAngle
//圓形定位的半徑
layout_constraintCircleRadius
來看一張官網(wǎng)的圖:
需要注意的是稿静,0°的位置是在目標控件的頂部。
來看一個時鐘表盤的布局吧
<?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_height="match_parent" android:layout_width="match_parent">
<TextView
android:id="@+id/tv_circle_label"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:text="Circle定位"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<TextView
android:id="@+id/btn_0"
android:layout_height="wrap_content"
android:layout_marginTop="120dp"
android:layout_width="wrap_content"
android:text="0"
android:textColor="@android:color/black"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_circle_label"/>
<TextView
android:id="@+id/btn_1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="1"
android:textColor="@android:color/black"
app:layout_constraintCircle="@id/btn_0"
app:layout_constraintCircleAngle="30"
app:layout_constraintCircleRadius="80dp"/>
<TextView
android:id="@+id/btn_2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="2"
android:textColor="@android:color/black"
app:layout_constraintCircle="@id/btn_0"
app:layout_constraintCircleAngle="60"
app:layout_constraintCircleRadius="80dp"/>
<TextView
android:id="@+id/btn_3"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="3"
android:textColor="@android:color/black"
app:layout_constraintCircle="@id/btn_0"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="80dp"/>
...
</android.support.constraint.ConstraintLayout>
強制約束
這個屬性是用于當(dāng)約束布局中的一個控件踪宠,由于其內(nèi)容很長自赔,導(dǎo)致該控件的寬度或者高度超出了范圍,導(dǎo)致布局上的錯亂柳琢,針對這個問題绍妨,ConstraintLayout很友善的提供了layout_constrainedWidth這個屬性润脸,當(dāng)設(shè)置為true時,會強制控件的寬高會在一個范圍內(nèi)他去,false則不強制毙驯。
我們來看個栗子:
代碼:
<?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_height="match_parent" android:layout_width="match_parent">
<CheckBox
android:checked="true"
android:id="@+id/cb_force_constraint"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:layout_width="wrap_content"
android:text="enforcing constraints"
android:textStyle="bold"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"/>
<Button
android:id="@+id/btn_add_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="add"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toLeftOf="@+id/btn_reduce_text"
app:layout_constraintTop_toBottomOf="@id/cb_force_constraint"/>
<Button
android:id="@+id/btn_reduce_text"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="reduce"
app:layout_constraintBaseline_toBaselineOf="@id/btn_add_text"
app:layout_constraintLeft_toRightOf="@id/btn_add_text"
app:layout_constraintRight_toRightOf="parent"/>
<Button
android:id="@+id/btn_m"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="M"
app:layout_constraintTop_toBottomOf="@id/btn_add_text"/>
<Button
android:id="@+id/btn_content"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
app:layout_constrainedWidth="true"
android:text="XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
app:layout_constraintLeft_toRightOf="@id/btn_m"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_m"/>
</android.support.constraint.ConstraintLayout>
Percent和Ratio
百分比布局也是UI設(shè)計師非常喜歡使用的,android支持包中原先有提供了一系列的百分比控件
寬高比布局android中就沒有了灾测,一般都是我們先固定寬或者高爆价,再計算出另一個邊
但是有了ContraintLayout,就可以通通不要了媳搪,原因很簡單铭段,俺們的ContraintLayout超棒的~
我們可以直接通過以下這個屬性來直接進行百分比控制:
layout_constraintDimensionRatio
這個屬性要怎么玩呢,其實也不復(fù)雜:
假如是固定寬度秦爆,要控制高度序愚,可以用"H,16:9"。
假如是固定高度等限,要控制寬度爸吮,可以用"W,16:9"
冒號左邊的是代表寬度,冒號右邊的是代表高度望门。
依舊來舉個栗子:
<?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:id="@+id/constraintLayout"
android:layout_height="match_parent" android:layout_width="match_parent">
<TextView
android:id="@+id/tv_title"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="百分比布局"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent"/>
<Button
android:id="@+id/btn_ratio_1"
android:layout_height="0dp"
android:layout_width="0dp"
android:text="Ratio_1"
app:layout_constraintDimensionRatio="H,16:9"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/tv_title"
app:layout_constraintWidth_percent="0.6"/>
<Button
android:id="@+id/btn_ratio_2"
android:layout_height="100dp"
android:layout_width="0dp"
android:text="Ratio_2"
app:layout_constraintDimensionRatio="W,16:9"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toBottomOf="@id/btn_ratio_1"/>
</android.support.constraint.ConstraintLayout>