和尚在很久以前了解過 ConstraintLayout 的基本用法,但實際應用的卻比較少;近來和尚在嘗試一些曆史項目的優化,對于 View-UI 繪制方面,準備通過 ConstraintLayout 來減少繪制層級;
Bias 偏向
ConstraintLayout 可以通過 _bias 屬性設定偏向于水準或豎直某一端;
- 使用 _bias 屬性時需要關聯水準或豎直方向的兩端關聯;若未設定關聯關系,單純的 _bias 偏向無效果;
- _bias 偏向與權重無關系,所謂偏向,是水準或豎直某一端距邊緣剩餘空間的占比;
- _bias 預設為 0.5 居中展示,整體範圍是 [0.0, 1.0];
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Center B (水準+豎直)"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
Circular positioning 圓形定位
ConstraintLayout 可以通過半徑和角度來設定兩個控件的關聯限制;
- app:layout_constraintCircle 用來設定關聯的控件,以此控件作為圓形中心;
- app:layout_constraintCircleAngle 用來設定兩個控件的相對角度,其範圍是 [0, 360],以順時針方向,豎直向上的為 0,與數學中的坐标系一緻;
- app:layout_constraintCircleRadius 作為圓形的半徑設定兩個控件的距離;
Button
android:id="@+id/circle_btn"
android:layout_width="30dp"
android:layout_height="30dp"
android:background="@drawable/btn_circle_red"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:layout_width="20dp"
android:layout_height="20dp"
android:background="@drawable/btn_circle_green"
app:layout_constraintCircle="@+id/circle_btn"
app:layout_constraintCircleAngle="90"
app:layout_constraintCircleRadius="160dp" />
Group 組的顯隐性
ConstraintLayout 減少了控件的 View 層級,但對于多個控件的顯隐形可以通過 Group 來處理;Group 通過設定 referenced_ids / setReferencedIds 将設定的控件數組統一管理,直接設定 Group 的顯隐性即可;
<androidx.constraintlayout.widget.Group
android:id="@+id/constract_group"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:constraint_referenced_ids="circle_item_btn1,circle_item_btn2,circle_item_btn3" />
mGroup.setVisibility(isVisible ? View.VISIBLE : View.GONE);
Chains 鍊式結構
和尚在使用 ConstraintLayout 時,對于多個控件的整體居中嘗試了鍊式結構;在學習過程中發現 Chains 有更多實用的效果;
和尚需要設定幾個控件共同居中,且這幾個控件的間距位置不變;
- 編輯設定多個預展示的控件;
- 選中需要設定的多個控件,右鍵 Chains 設定 Create Vertical Chains;如圖展示,雖然整體居中,但控件間的相對間隔也改變了;因為預設的 _chainStyle 為 spread 樣式;
- 設定最頂部鍊頭屬性 app:layout_constraintVertical_chainStyle="packed";
鍊式結構的整體效果主要是通過 Chains Head 鍊頭來決定!
ChainStyle - spread
spread 為平均分散排列,及各個控件間的距離是均分的(不包括控件自身設定的 margin / padding 屬性);
ChainStyle - spread_inside
spread_inside 也是平均分散排列,其中兩端預設是緊臨水準或豎直兩端的(不包括控件自身設定的 margin / padding 屬性);
ChainStyle - packed
packed 是把鍊式結構中關聯的控件組作為一個整體進行排列,可以設定 Bias 整體偏向等;
<?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"
android:layout_width="match_parent"
android:layout_height="match_parent">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:text="今日推薦" android:textSize="20sp"
android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/imageView"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent"
app:layout_constraintVertical_chainStyle="packed" />
<ImageView
android:id="@+id/imageView"
android:layout_width="match_parent" android:layout_height="wrap_content"
android:layout_marginTop="30dp" android:src="@mipmap/icon_hzw"
app:layout_constraintBottom_toTopOf="@+id/textView2"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView" />
<TextView
android:id="@+id/textView2"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:text="布魯克"
android:textColor="@android:color/holo_green_dark"
android:textSize="20sp" android:textStyle="bold"
app:layout_constraintBottom_toTopOf="@+id/textView5"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/imageView" />
<TextView
android:id="@+id/textView5"
android:layout_width="wrap_content" android:layout_height="wrap_content"
android:layout_marginTop="20dp" android:background="@drawable/btn_circle_gray"
android:padding="10dp" android:text="點選詳情"
android:textColor="@android:color/darker_gray" android:textSize="20sp"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toBottomOf="@+id/textView2" />
</androidx.constraintlayout.widget.ConstraintLayout>
Weighted Chains 權重鍊
類似于 LinearLayout 中的 widget 權重,ConstraintLayout 也可以通過 _weight 設定權重效果;其中使用權重時需優先設定好 Chains 鍊式結構;
<View
android:id="@+id/view"
android:layout_width="0dp"
android:layout_height="120dp"
android:background="@color/colorPrimary"
app:layout_constraintEnd_toStartOf="@+id/view2"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toStartOf="parent" />
<View
android:id="@+id/view2"
android:layout_width="0dp"
android:layout_height="120dp"
android:background="@color/colorAccent"
app:layout_constraintEnd_toStartOf="@+id/view3"
app:layout_constraintHorizontal_weight="2"
app:layout_constraintStart_toEndOf="@+id/view" />
<View
android:id="@+id/view3"
android:layout_width="0dp"
android:layout_height="120dp"
android:background="@color/colorPrimary"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintHorizontal_weight="1"
app:layout_constraintStart_toEndOf="@+id/view2" />
Gone Margins 隐藏外邊距
在應用中,margins 為外邊距,在使用 ConstraintLayout 關聯布局時,添了 _goneMargin 屬性;即控件 B 是以控件 A 作為關聯基礎,當控件 A 動态隐藏時,可以通過 _goneMargin 設定控件 B 的新的外邊距;其中 _goneMargin 屬性需要設定在非隐藏控件 B 中;
<TextView
android:id="@+id/view7"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:background="@color/colorPrimary"
android:text="A"
android:visibility="gone"
app:layout_constraintEnd_toStartOf="@+id/view8"
app:layout_constraintStart_toStartOf="@+id/imageView"
app:layout_constraintTop_toBottomOf="@+id/item_tv3" />
<TextView
android:id="@+id/view8"
android:layout_width="100dp"
android:layout_height="100dp"
android:layout_marginLeft="15dp"
android:background="@color/colorAccent"
android:text="B"
app:layout_constraintEnd_toStartOf="@+id/view9"
app:layout_constraintStart_toEndOf="@+id/view7"
app:layout_constraintTop_toBottomOf="@+id/item_tv3"
app:layout_goneMarginLeft="30dp"
app:layout_goneMarginStart="30dp" />
和尚這次整理的還很淺顯,未曾設計源碼,主要是之前應用較少的場景,對于層級的優化還是很重要的;如有錯誤,請多多指導!
來源: 阿策小和尚