ConstraintLayout 想說愛你不容易 (二)

fondtiger發表於2021-09-09

      和尚在很久以前瞭解過 ConstraintLayout 的基本用法,但實際應用的卻比較少;近來和尚在嘗試一些歷史專案的最佳化,對於 View-UI 繪製方面,準備透過 ConstraintLayout 來減少繪製層級;

Bias 偏向

      ConstraintLayout 可以透過 _bias 屬性設定偏向於水平或豎直某一端;

  1. 使用 _bias 屬性時需要關聯水平或豎直方向的兩端關聯;若未設定關聯關係,單純的 _bias 偏向無效果;
  2. _bias 偏向與權重無關係,所謂偏向,是水平或豎直某一端距邊緣剩餘空間的佔比;
  3. _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 可以透過半徑和角度來設定兩個控制元件的關聯約束;

  1. app:layout_constraintCircle 用來設定關聯的控制元件,以此控制元件作為圓形中心;
  2. app:layout_constraintCircleAngle 用來設定兩個控制元件的相對角度,其範圍是 [0, 360],以順時針方向,豎直向上的為 0,與數學中的座標系一致;
  3. 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 有更多實用的效果;

      和尚需要設定幾個控制元件共同居中,且這幾個控制元件的間距位置不變;

  1. 編輯設定多個預展示的控制元件;

圖片描述
2. 選中需要設定的多個控制元件,右鍵 Chains 設定 Create Vertical Chains;如圖展示,雖然整體居中,但控制元件間的相對間隔也改變了;因為預設的 _chainStylespread 樣式;

圖片描述
3. 設定最頂部鏈頭屬性 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=""
    xmlns:app=""
    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:class="lazyload" src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" data-original="@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" />

圖片描述


      和尚這次整理的還很淺顯,未曾設計原始碼,主要是之前應用較少的場景,對於層級的最佳化還是很重要的;如有錯誤,請多多指導!

來源: 阿策小和尚

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/2508/viewspace-2825698/,如需轉載,請註明出處,否則將追究法律責任。

相關文章