在 Compose 中,您可以將多個修飾符鏈結在一起,以變更可組合函式的外觀和風格。這些修飾符鏈結可能會影響傳遞至可組合項的限制,這些限制會定義寬度和高度邊界。
本頁說明鏈結修飾符如何影響限制條件,進而影響可組合項的測量和放置方式。
UI 樹狀結構中的修飾符
如要瞭解修飾符如何相互影響,建議您以視覺化方式呈現這些修飾符在 UI 樹狀結構中的顯示方式,這類樹狀結構會在組合階段產生。詳情請參閱「組合」一節。
在 UI 樹狀結構中,您可以將修飾符視為版面配置節點的包裝函式節點:
在可組合項中新增多個修飾符,即可建立修飾符鏈結。鏈結多個修飾符時,每個修飾符節點都會包裝其餘的鏈結和內部版面配置節點。舉例來說,當您鏈結 clip
和 size
修飾符時,clip
修飾符節點會包裝 size
修飾符節點,而 size
修飾符節點會包裝 Image
版面配置節點。
在版面配置階段,遍歷樹狀結構的演算法會維持不變,但也會造訪每個修飾符節點。這樣一來,修飾符就能變更所包裝修飾符或版面配置節點的大小需求和位置。
如圖 2 所示,Image
和 Text
可組合項的實作內容包含包裝單一版面配置節點的修飾符鏈結。Row
和 Column
的實作項目只是版面配置節點,用於說明如何版面配置子項。
總結來說:
- 修飾符會包裝單一修飾符或版面配置節點。
- 版面配置節點可排版多個子節點。
以下各節將說明如何使用這個概念模型,推論修飾符鏈結的情形,以及鏈結會如何影響可組合項的大小。
版面配置階段中的限制
版面配置階段會按照三步驟演算法找出每個版面配置節點的寬度、高度和 x、y 座標:
- 測量子項:節點會測量其子項 (如果有)。
- 決定自身大小:節點會根據這些測量值決定自身大小。
- 放置子項:每個子項節點都會相對於節點本身的位置放置。
Constraints
可在演算法的前兩個步驟中,協助找出節點的正確大小。限制會定義節點寬度和高度的最小和最大邊界。節點決定其大小時,其測量大小應落在這個大小範圍內。
限制條件的類型
限制可以是下列任一項目:
- 有邊界:節點有寬度和高度的上限和下限。
- 無限制:節點不受任何大小限制。寬度和高度上限範圍設為無限。
- Exact:要求節點遵循確切大小規定。最小和最大邊界都設為相同的值。
- 組合:節點會遵循上述約束條件類型的組合。舉例來說,限制條件可以限制寬度,同時允許無上限的高度,或是設定確切的寬度,但提供受限的高度。
下一節將說明如何將這些限制條件從父項傳遞至子項。
限制如何從父項傳遞至子項
在「版面配置階段中的限制條件」一文中所述演算法的首個步驟中,限制條件會從 UI 樹狀結構中的父項傳遞至子項。
父項節點測量子項時,會向每個子項提供這些限制,讓子項知道允許的大小範圍。接著,當它決定自身大小時,也會遵循其自身父項傳入的限制條件。
大致來說,演算法的運作方式如下:
- 為了決定實際要占用的大小,UI 樹狀結構中的根節點會測量其子項,並將相同的限制條件轉送至第一個子項。
- 如果子項是不會影響測量值的修飾符,則會將限制轉寄至下一個修飾符。除非遇到會影響測量值的修飾符,否則限制條件會原封不動地傳遞至修飾符鏈結。然後再根據計算結果重新調整限制。
- 一旦到達沒有任何子項的節點 (稱為「葉節點」),系統就會根據傳入的限制決定其大小,並將這個已解析的大小傳回至父項。
- 父項會根據這個子項的測量值調整限制條件,並使用這些調整後的限制條件呼叫下一個子項。
- 父項的所有子項都完成測量後,父項節點會決定自身的大小,並將該大小傳達給自身的父項。
- 這樣一來,整個樹狀結構就會以深度優先的方式進行檢查。最後,所有節點都已決定其大小,測量步驟也已完成。
如需深入瞭解範例,請觀看「限制和修飾符順序」影片。
影響限制條件的修飾符
您在上一節中瞭解到,某些修飾符可能會影響約束條件大小。以下各節說明會影響限制條件的特定修飾符。
size
修飾符
size
修飾符會宣告內容的偏好大小。
舉例來說,下列 UI 樹狀結構應由 200dp
轉換為 300dp
的容器,並進行轉譯。限制條件設有邊界,寬度介於 100dp
和 300dp
之間,高度介於 100dp
和 200dp
之間:
size
修飾符會調整傳入的限制條件,以符合傳遞給它的值。在這個範例中,這個值為 150dp
:
如果寬度和高度小於最小限制邊界,或大於最大限制邊界,修飾符會盡可能與傳入的限制相符,同時遵循以下傳入的限制:
請注意,連接多個 size
修飾符不會生效。第一個 size
修飾符會將最小和最大限制設為固定值。即使第二個大小修飾符要求較小或較大的大小,仍需遵循傳入的確切邊界,因此不會覆寫這些值:
requiredSize
修飾符
如果需要節點覆寫輸入的限制,請使用 requiredSize
修飾符,而非 size
。requiredSize
修飾符會取代傳入的限制條件,並將您指定的大小傳遞為確切邊界。
當大小傳回樹狀結構時,子節點會置中於可用空間:
width
和 height
修飾符
size
修飾符會調整限制條件的寬度和高度。您可以使用 width
修飾符來設定固定寬度,但高度則不需指定。同樣地,您可以使用 height
修飾符來設定固定高度,但寬度則不需指定:
sizeIn
修飾符
sizeIn
修飾符可讓您設定寬度和高度的確切最小和最大限制。如果您需要精細控制限制,請使用 sizeIn
修飾符。
範例
本節會顯示並說明多個含有鏈結修飾符的程式碼片段輸出內容。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .size(50.dp) )
這個程式碼片段會產生以下輸出內容:
fillMaxSize
修飾符會變更限制,將最小寬度和高度都設為最大值,也就是寬度為300dp
,高度為200dp
。- 即使
size
修飾符想使用50dp
的大小,仍需遵循輸入的最小限制。因此,size
修飾符也會透過200
輸出300
的確切限制邊界,有效地忽略size
修飾符中提供的值。 Image
會遵循這些邊界,並透過200
回報300
的大小,而這會一直傳遞至樹狀結構的頂端。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .fillMaxSize() .wrapContentSize() .size(50.dp) )
這個程式碼片段會產生以下輸出內容:
fillMaxSize
修飾符會調整限制條件,將最小寬度和高度都設為最大值,也就是寬度為300dp
,高度為200dp
。wrapContentSize
修飾符會重設最小限制。因此,當fillMaxSize
導致固定限制時,wrapContentSize
會將其重設為受限限制。以下節點現在可以再次占用整個空間,或小於整個空間。size
修飾符會將限制設為50
的最小和最大邊界。Image
會透過50
解析為50
的大小,而size
修飾符會將其傳遞出去。wrapContentSize
修飾符具有特殊屬性。它會取得子項,並將其置於傳遞的可用最小邊界的中心。因此,傳送至父項的大小會等於傳入的邊界下限。
只要結合三個修飾符,即可為可組合項定義大小,並將其置於父項的中央。
Image( painterResource(R.drawable.hero), contentDescription = null, Modifier .clip(CircleShape) .padding(10.dp) .size(100.dp) )
這個程式碼片段會產生以下輸出內容:
clip
修飾符不會變更約束條件。padding
修飾符會降低最大限制。size
修飾符會將所有限制設為100dp
。Image
會遵循這些限制,並透過100dp
回報100
的大小。padding
修飾符會在所有大小上加上10dp
,因此會將回報的寬度和高度增加20dp
。- 在繪圖階段,
clip
修飾符會透過120dp
對120
的畫布執行動作。因此,它會建立該大小的圓形遮罩。 - 接著,
padding
修飾符會在所有大小上將內容內嵌10dp
,因此會將畫布大小降低100dp
至100
。 Image
會在該畫布中繪製。系統會根據120dp
的原始圓形裁剪圖片,因此輸出結果並非圓形。