前言
什么是約束布局(ConstraintLayout)
我們可以理解為增強(qiáng)版/升級(jí)版的相對(duì)布局(RelativeLayout)。
Android Studio 從版本2.3開始創(chuàng)建xml默認(rèn)的根布局就是約束布局,相信大家對(duì)相對(duì)布局已經(jīng)是使用的非常6了客峭,所有在使用約束布局的話就會(huì)比較輕松。
那么既然已經(jīng)有相對(duì)布局了鼠锈,為什么還要用約束布局呢?最核心就是:
讓布局扁平化,減少布局嵌套的層次横缔,提高渲染效率,提升應(yīng)用性能膛锭。
所以說約束布局還是很有必要學(xué)一學(xué)的,最起碼在性能優(yōu)化方面是很有幫助的。
下面就一起開始學(xué)習(xí)吧腥光!
廢話不多說,直接進(jìn)入主題艘儒。
舉個(gè)最簡單的栗子:
將一個(gè)在ConstraintLayout中居中,如下:
代碼很簡單,就是給TextView添加上下左右邊界的約束即可访惜。所以寫約束布局就是寫控件的邊界約束砾嫉。
下面我們先介紹下約束屬性的寫法以及含義。
app:layout_constraintStart_toStartOf="parent"
我們來解釋下屬性:
第一個(gè)start代表的是控件自身的約束方向。
第二個(gè)start代表的目標(biāo)控件的約束方向溉旋。
第三個(gè)parent代表的是和那個(gè)控件建立約束。如果是父控件,就填parent婶溯,如果是其他控件,就填寫控件的id叙身。
下面我們就以最實(shí)用的現(xiàn)實(shí)場景來簡單學(xué)習(xí)下ConstraintLayout。
- 控件水平排列
代碼如下:<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <TextView android:id="@+id/common_textview" android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="50dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/common_textview2" android:layout_width="100dp" android:layout_height="100dp" app:layout_constraintStart_toEndOf="@+id/common_textview" app:layout_constraintTop_toTopOf="@+id/common_textview" /> <TextView android:layout_width="100dp" android:layout_height="100dp" app:layout_constraintStart_toEndOf="@+id/common_textview2" app:layout_constraintTop_toTopOf="@+id/common_textview" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
同理垂直方向上的排列就不多說了泣侮。
- 垂直方向居中
代碼如下:<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <TextView android:id="@+id/common_textview" android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="50dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/common_textview2" android:layout_width="100dp" android:layout_height="wrap_content" app:layout_constraintBottom_toBottomOf="@+id/common_textview" app:layout_constraintStart_toEndOf="@+id/common_textview" app:layout_constraintTop_toTopOf="@+id/common_textview" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
重點(diǎn):讓控件自身的上邊界和先邊界分別和目標(biāo)控件的上下邊界進(jìn)行對(duì)應(yīng)約束即可漏益。
- 垂直居中的同時(shí),高度一致
<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <TextView android:id="@+id/common_textview" android:layout_width="100dp" android:layout_height="100dp" android:layout_margin="50dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/common_textview2" android:layout_width="100dp" android:layout_height="0dp" android:layout_marginStart="70dp" app:layout_constraintBottom_toBottomOf="@+id/common_textview" app:layout_constraintStart_toEndOf="@+id/common_textview" app:layout_constraintTop_toTopOf="@+id/common_textview" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
其實(shí)很簡單权埠,只需要將控件自身的高度設(shè)置為0dp即可,0dp的意思就是match constraint满俗,就是充滿約束。
- 基于某個(gè)控件的下邊界線居中
代碼如下:<?xml version="1.0" encoding="utf-8"?> <androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" xmlns:app="http://schemas.android.com/apk/res-auto"> <TextView android:background="#FFD115" android:id="@+id/common_textview" android:layout_width="match_parent" android:layout_height="100dp" android:layout_margin="50dp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView app:layout_constraintStart_toStartOf="@id/common_textview" app:layout_constraintEnd_toEndOf="@id/common_textview" app:layout_constraintTop_toBottomOf="@id/common_textview" app:layout_constraintBottom_toBottomOf="@id/common_textview" android:background="@color/color_FFD115" android:id="@+id/common_textview2" android:layout_width="60dp" android:layout_height="50dp" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
重點(diǎn):控件自身的垂直約束方向都和目標(biāo)控件的底邊建立約束即可沉删。
- 權(quán)重平分空間
寬度相同砖茸,平分間距。
代碼如下:<?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"> <View android:id="@+id/common_view" android:layout_width="100dp" android:layout_height="100dp" app:layout_constraintEnd_toStartOf="@id/common_view2" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <View android:id="@+id/common_view2" android:layout_width="100dp" android:layout_height="100dp" app:layout_constraintEnd_toStartOf="@id/common_view3" app:layout_constraintStart_toEndOf="@id/common_view" app:layout_constraintTop_toTopOf="parent" /> <View android:id="@+id/common_view3" android:layout_width="100dp" android:layout_height="100dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@id/common_view2" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
控件寬度平分,只需要改變上述代碼中的android:layout_width="0dp"
即可實(shí)現(xiàn)。
代碼如下:
<?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">
<View
android:id="@+id/common_view"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toStartOf="@id/common_view2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/common_view2"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toStartOf="@id/common_view3"
app:layout_constraintStart_toEndOf="@id/common_view"
app:layout_constraintTop_toTopOf="parent" />
<View
android:id="@+id/common_view3"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/common_view2"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果圖如下:
重點(diǎn):讓寬度為0dp,充滿約束即可拐邪。
根據(jù)不同的權(quán)重實(shí)現(xiàn)不同比例的平分,這里的權(quán)重的使用必須是充滿約束才會(huì)生效,即寬度為0dp惰赋,而且約束布局的權(quán)重分為垂直和水平兩個(gè)方向。
代碼如下:
<?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">
<View
android:id="@+id/common_view"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintHorizontal_weight="3"
app:layout_constraintEnd_toStartOf="@id/common_view2"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<View
app:layout_constraintHorizontal_weight="2"
android:id="@+id/common_view2"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toStartOf="@id/common_view3"
app:layout_constraintStart_toEndOf="@id/common_view"
app:layout_constraintTop_toTopOf="parent" />
<View
app:layout_constraintHorizontal_weight="1"
android:id="@+id/common_view3"
android:layout_width="0dp"
android:layout_height="100dp"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toEndOf="@id/common_view2"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
效果圖如下:
這里只寫了水平方向上的權(quán)重挨务,垂直方向上的權(quán)重同理果漾。
- 不同大小文字的對(duì)齊(基準(zhǔn)線對(duì)齊)
代碼如下:<?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"> <TextView android:id="@+id/view1" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:text="78" android:textSize="128sp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView app:layout_constraintStart_toEndOf="@+id/view1" app:layout_constraintBaseline_toBaselineOf="@+id/view1" android:text="%" android:textSize="40sp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView android:id="@+id/view2" android:layout_marginTop="260dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" android:text="78" android:textSize="128sp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> <TextView app:layout_constraintStart_toEndOf="@+id/view2" app:layout_constraintBottom_toBottomOf="@+id/view2" android:text="%" android:textSize="40sp" android:layout_width="wrap_content" android:layout_height="wrap_content"/> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
-
角度定位
使用角度定位需要3個(gè)條件:1.圓心 2.半徑 3.角度户辱。其中角度是從正上方順時(shí)針開始的。
代碼如下:<?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"> <ImageView android:id="@+id/view_sun" android:layout_width="80dp" android:layout_height="80dp" android:src="@drawable/sun" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/view_earth" android:layout_width="40dp" android:layout_height="40dp" android:src="@drawable/earth" app:layout_constraintCircle="@+id/view_sun" app:layout_constraintCircleAngle="45" app:layout_constraintCircleRadius="150dp" /> <ImageView android:id="@+id/view_moon" android:layout_width="20dp" android:layout_height="20dp" android:src="@drawable/moon" app:layout_constraintCircle="@+id/view_earth" app:layout_constraintCircleAngle="130" app:layout_constraintCircleRadius="30dp" /> </androidx.constraintlayout.widget.ConstraintLayout>
說明:
layout_constraintCircle
以哪個(gè)view為圓心
layout_constraintCircleRadius
圓的半徑
layout_constraintCircleAngle
旋轉(zhuǎn)角度, 以第一象限順時(shí)針開始粟矿。效果如下:
-
約束寬度
一個(gè)文本的長度不能超過圖片的寬度。
代碼如下:<?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:background="@android:color/black" android:layout_height="match_parent"> <ImageView android:src="@drawable/sun" android:scaleType="fitXY" android:id="@+id/view1" android:layout_width="260dp" android:layout_height="80dp" android:layout_marginTop="50dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:layout_marginTop="10dp" android:textColor="@android:color/white" app:layout_constrainedWidth="true" android:layout_width="wrap_content" android:layout_height="wrap_content" android:gravity="center" android:text="文本很長很長文本很長很長文本很長很長文本很長很長文本很長很長文本很長很長" android:textSize="12sp" app:layout_constraintEnd_toEndOf="@+id/view1" app:layout_constraintStart_toStartOf="@+id/view1" app:layout_constraintTop_toBottomOf="@+id/view1" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
可以看到文本的整體的寬度被約束為和上面的圖片等寬荆姆,高度的約束也是同理蒙幻。
-
bias,約束傾向胞枕,取值范圍:0.0-1.0杆煞。 0.0最左側(cè)魏宽,1.0最右側(cè)。一般配合約束寬度來使用队询。
看下聊天的UI效果如下:
文字短的時(shí)候包裹內(nèi)容派桩,超過最大寬度換行展示。
代碼如下:<?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" android:background="@android:color/black"> <ImageView android:id="@+id/view1" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginTop="50dp" android:scaleType="fitXY" android:layout_marginStart="15dp" android:src="@drawable/sun" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:paddingTop="3dp" android:paddingBottom="3dp" android:paddingStart="2dp" android:paddingEnd="2dp" android:background="@android:color/holo_red_dark" android:layout_marginEnd="15dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0" app:layout_constrainedWidth="true" app:layout_constraintStart_toEndOf="@+id/view1" app:layout_constraintTop_toTopOf="@+id/view1" android:layout_marginStart="8dp" android:text="君不見蚌斩,黃河之水天上來铆惑,奔流到海不復(fù)回。君不見送膳,高堂明鏡悲白發(fā)员魏,朝如青絲暮成雪。人生得意須盡歡叠聋,莫使金樽空對(duì)月撕阎。" android:textColor="@android:color/white" android:textSize="16sp" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
-
短文字效果
-
中等文字效果
-
超長文字效果
水平方向上的約束傾向如上,垂直方向上的約束傾向同理碌补。
- GoneMargin虏束。當(dāng)約束目標(biāo)控件隱藏時(shí),控件自身可以保留一定的間距厦章。
代碼如下:<?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" android:background="@android:color/black"> <ImageView android:visibility="gone" android:id="@+id/view1" android:layout_width="40dp" android:layout_height="40dp" android:layout_marginTop="50dp" android:scaleType="fitXY" android:layout_marginStart="15dp" android:src="@drawable/sun" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView app:layout_goneMarginStart="30dp" android:paddingTop="3dp" android:paddingBottom="3dp" android:paddingStart="2dp" android:paddingEnd="2dp" android:background="@android:color/holo_red_dark" android:layout_marginEnd="15dp" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintHorizontal_bias="0" app:layout_constrainedWidth="true" app:layout_constraintStart_toEndOf="@+id/view1" app:layout_constraintTop_toTopOf="@+id/view1" android:layout_marginStart="8dp" android:text="君不見镇匀,黃河之水天上來,奔流到海不復(fù)回袜啃。君不見汗侵,高堂明鏡悲白發(fā),朝如青絲暮成雪。人生得意須盡歡晰韵,莫使金樽空對(duì)月冀值。" android:textColor="@android:color/white" android:textSize="16sp" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
-
正常情況
- 當(dāng)約束控件隱藏,但是不加
GoneMargin
屬性宫屠。
- 當(dāng)約束控件隱藏列疗,加上
GoneMargin
屬性。
可以看出來GoneMargin
的作用了吧浪蹂。
-
約束鏈風(fēng)格 ChainStyle
風(fēng)格:packed(打包抵栈,組合),spread(擴(kuò)散坤次,默認(rèn))古劲,spread_inside(內(nèi)部擴(kuò)散)。而且約束鏈風(fēng)格必須寫在第一個(gè)控件上才有效缰猴。- 組件組合后居中
代碼如下:<?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" android:background="@android:color/black"> <ImageView android:id="@+id/view1" android:layout_width="40dp" android:layout_height="40dp" android:scaleType="fitXY" android:src="@drawable/sun" app:layout_constraintVertical_chainStyle="packed" app:layout_constraintBottom_toTopOf="@+id/view2" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/view2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_red_dark" android:paddingStart="2dp" android:paddingTop="3dp" android:paddingEnd="2dp" android:paddingBottom="3dp" android:text="君不見产艾,黃河之水天上來,奔流到海不復(fù)回滑绒。" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/view1" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
而且還支持約束傾向bias.水平方向同理闷堡。
- 組件內(nèi)部擴(kuò)散
代碼如下:
<?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" android:background="@android:color/black"> <View app:layout_constraintHorizontal_chainStyle="spread_inside" android:id="@+id/view1" android:layout_width="100dp" android:layout_height="200dp" android:background="@android:color/holo_red_dark" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/view2" app:layout_constraintStart_toStartOf="parent" /> <View android:id="@+id/view2" android:layout_width="100dp" android:layout_height="200dp" android:background="@android:color/holo_red_dark" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/view3" app:layout_constraintStart_toEndOf="@+id/view1" /> <View android:id="@+id/view3" android:layout_width="100dp" android:layout_height="200dp" android:background="@android:color/holo_red_dark" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/view2" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
垂直方向同理。
- 組件內(nèi)部擴(kuò)散
- 組件組合后居中
-
控件寬高比例保持一致疑故, DimensionRatio
使用這個(gè)屬性的前提是杠览,控件的寬或者高至少有一個(gè)是充滿約束的,即為0dp纵势。
代碼如下:<?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" android:background="@android:color/black"> <ImageView android:id="@+id/view1" android:layout_width="200dp" android:layout_height="0dp" app:layout_constraintDimensionRatio="2:1" android:background="@drawable/sun" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> </androidx.constraintlayout.widget.ConstraintLayout>
寬高比:2:1
效果如下:
如果寬和高都是0dp踱阿,DimensionRatio需要加上“H,2:1”,這個(gè)H說明高度是計(jì)算出來的钦铁,也就是說寬度充滿約束软舌,這里就不再演示了。
- 百分比布局牛曹,寬度或者高度占parent的百分比
這個(gè)百分比始終是針對(duì)parent的百分比佛点,而且使用百分比的前提是寬度或者高度必須充滿約束,即0dp躏仇。
代碼如下:<?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" android:background="@android:color/black"> <View android:background="@android:color/holo_red_dark" android:layout_width="0dp" app:layout_constraintTop_toTopOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintWidth_percent="0.3" android:layout_height="320dp"/> <View android:background="@android:color/holo_green_dark" android:layout_width="0dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintTop_toTopOf="parent" app:layout_constraintWidth_percent="0.5" android:layout_height="320dp"/> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
第一個(gè)View 寬度占parent 的30%恋脚, 第二個(gè)View寬度占parent的50%,垂直方向上的百分比同理焰手。
- GuideLine(基準(zhǔn)線/輔助線)
這個(gè)是輔助控件糟描,輔助控件之間的約束,而不是一個(gè)真正的控件书妻。
下面舉一個(gè)簡單的UI栗子船响,比如登錄頁面躬拢。
代碼如下:<?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" android:background="@android:color/black"> <androidx.constraintlayout.widget.Guideline android:id="@+id/guide_line" android:layout_width="wrap_content" android:layout_height="wrap_content" android:orientation="vertical" app:layout_constraintGuide_percent="0.2" /> <TextView android:id="@+id/tv_username" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="70dp" android:paddingTop="20dp" android:paddingBottom="20dp" android:text="用戶名" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintEnd_toStartOf="@+id/guide_line" app:layout_constraintTop_toTopOf="parent" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:background="@android:color/white" android:hint="輸入用戶名" android:textColorHint="@android:color/black" app:layout_constraintBaseline_toBaselineOf="@id/tv_username" app:layout_constraintStart_toEndOf="@+id/guide_line" /> <TextView android:id="@+id/tv_password" android:layout_width="wrap_content" android:layout_height="wrap_content" android:paddingTop="20dp" android:paddingBottom="20dp" android:text="密碼" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintEnd_toStartOf="@+id/guide_line" app:layout_constraintTop_toBottomOf="@+id/tv_username" /> <EditText android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="8dp" android:background="@android:color/white" android:hint="輸入密碼" android:textColor="@android:color/black" android:textColorHint="@android:color/black" app:layout_constraintBaseline_toBaselineOf="@+id/tv_password" app:layout_constraintStart_toEndOf="@+id/guide_line" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
- Group
當(dāng)某一種狀態(tài)下需要多好多控件進(jìn)行隱藏和顯示時(shí),可以使用Group见间,來統(tǒng)一顯示和隱藏聊闯。
代碼如下:<?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" android:background="@android:color/black"> <androidx.constraintlayout.widget.Group android:id="@+id/group1" android:layout_width="wrap_content" android:visibility="gone" android:layout_height="wrap_content" app:constraint_referenced_ids="tv1,tv2" /> <androidx.constraintlayout.widget.Group android:id="@+id/group2" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="tv3,tv4" /> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="10dp" android:padding="15dp" android:text="group1" android:textColor="@android:color/white" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="15dp" android:text="group1-2" android:textColor="@android:color/white" app:layout_constraintStart_toEndOf="@+id/tv1" app:layout_constraintTop_toTopOf="@+id/tv1" /> <TextView android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="30dp" android:layout_marginTop="80dp" android:padding="15dp" android:text="group2" android:textColor="@android:color/white" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:padding="15dp" android:text="group2-1" android:textColor="@android:color/white" app:layout_constraintStart_toEndOf="@+id/tv3" app:layout_constraintTop_toTopOf="@+id/tv3" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
設(shè)置Group1的visibility=visible時(shí),效果如下:
設(shè)置Group1的visibility=gone時(shí)米诉,效果如下:
- Layer
也是一個(gè)約束輔助菱蔬,它的使用和Group類似,只不過layer可以對(duì)整體進(jìn)行旋轉(zhuǎn)史侣,平移等常用的操作拴泌。
代碼如下:public class CommonTest extends FragmentActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.common_constraint_layout_demo); findViewById(R.id.layer).setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { //旋轉(zhuǎn)45d° findViewById(R.id.layer).setRotation(45); //X軸向右平移100px findViewById(R.id.layer).setTranslationX(100); //Y軸向下平移100px findViewById(R.id.layer).setTranslationY(100); } }); } }
<?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" android:background="@android:color/black"> <Button android:id="@+id/button" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="5dp" android:layout_marginTop="10dp" android:text="旋轉(zhuǎn)" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <androidx.constraintlayout.helper.widget.Layer android:id="@+id/layer" android:layout_width="wrap_content" android:layout_height="wrap_content" app:constraint_referenced_ids="tv1,tv2,tv3,tv4" tools:ignore="MissingConstraints" /> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="15dp" android:layout_marginTop="10dp" android:background="@android:color/holo_blue_light" android:padding="10dp" android:text="text1" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/button" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_green_dark" android:padding="10dp" android:text="text2" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintStart_toEndOf="@+id/tv1" app:layout_constraintTop_toTopOf="@+id/tv1" /> <TextView android:id="@+id/tv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginStart="30dp" android:layout_marginTop="40dp" android:background="@android:color/darker_gray" android:padding="10dp" android:text="text3" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintStart_toStartOf="@+id/tv1" app:layout_constraintTop_toBottomOf="@+id/tv1" /> <TextView android:id="@+id/tv4" android:layout_width="wrap_content" android:layout_height="wrap_content" android:background="@android:color/holo_purple" android:padding="10dp" android:text="text4" android:textColor="@android:color/white" android:textSize="16sp" app:layout_constraintStart_toEndOf="@+id/tv3" app:layout_constraintTop_toTopOf="@+id/tv3" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
- Barrier
屏障,柵欄。給約束控件設(shè)置約束上的屏障惊橱,已達(dá)到約束位置的目的蚪腐。
代碼如下:<?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" android:background="@android:color/black" tools:context=".ui.CommonTest"> <androidx.constraintlayout.widget.Barrier android:id="@+id/barrier" android:layout_width="wrap_content" android:layout_height="wrap_content" app:barrierDirection="end" app:constraint_referenced_ids="tv1,tv2" tools:ignore="MissingConstraints" /> <TextView android:id="@+id/tv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="15dp" android:text="文本1文本1文本1文本1文本1" android:textColor="@android:color/white" android:textSize="15sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <TextView android:id="@+id/tv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_marginTop="30dp" android:text="文本2文本2" android:textColor="@android:color/white" android:textSize="15sp" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toBottomOf="@+id/tv1" /> <ImageView android:id="@+id/iv1" android:layout_width="25dp" android:layout_height="25dp" android:src="@drawable/moon" app:layout_constraintStart_toEndOf="@+id/barrier" app:layout_constraintTop_toTopOf="@+id/tv1" /> <ImageView android:id="@+id/iv2" android:layout_width="25dp" android:layout_height="25dp" android:src="@drawable/moon" app:layout_constraintStart_toEndOf="@+id/barrier" app:layout_constraintTop_toTopOf="@+id/tv2" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
像:Group,Layer税朴,Barrier都是以ID的引用來實(shí)現(xiàn)的回季,所以如果使用了特殊的混淆工具,對(duì)id資源進(jìn)行了混淆正林,這里就需要注意下泡一,不然運(yùn)行起來會(huì)找不到id的。
- Placeholder
占位符卓囚。
代碼如下:public class CommonTest extends FragmentActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.common_constraint_layout_demo); } public void onClick(View view) { findViewById(R.id.placeholder).setContentId(view.getId()); } }
<?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" android:background="@android:color/black" tools:context=".ui.CommonTest"> <androidx.constraintlayout.widget.Placeholder android:id="@+id/placeholder" android:layout_width="50dp" android:layout_height="50dp" android:layout_marginTop="20dp" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" app:layout_constraintTop_toTopOf="parent" /> <ImageView android:id="@+id/iv1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/sun" app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toStartOf="@+id/iv2" app:layout_constraintStart_toStartOf="parent" /> <ImageView android:id="@+id/iv2" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/earth" app:layout_constraintEnd_toStartOf="@+id/iv3" app:layout_constraintStart_toEndOf="@+id/iv1" app:layout_constraintTop_toTopOf="@+id/iv1" /> <ImageView android:id="@+id/iv3" android:layout_width="wrap_content" android:layout_height="wrap_content" android:src="@drawable/moon" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toEndOf="@+id/iv2" app:layout_constraintTop_toTopOf="@+id/iv1" /> </androidx.constraintlayout.widget.ConstraintLayout>
效果如下:
當(dāng)點(diǎn)擊下面3個(gè)view其中一個(gè)view的時(shí)候瘾杭,被點(diǎn)擊的view會(huì)被替換到上面的Placeholder所在的位置。