Jetpack Compose 建築分層

本頁面會概略說明構成 Jetpack Compose 的架構層和基礎原則,並提供這項設計的重要概念。

Jetpack Compose 並非單一單體式專案;是由多個模組結合而成,以組成完整的堆疊。瞭解構成 Jetpack Compose 的各種不同模組,您就能:

  • 使用適當的抽象層建構您的應用程式或程式庫
  • 瞭解何時可以「下滑」到層級較低的位置,進一步自訂或自訂
  • 盡可能減少依附元件

圖層

Jetpack Compose 的主要層如下:

圖 1. Jetpack Compose 的主要層。

每一層都是以較低層級建構而成,結合多項功能以建立較高層級的元件。每一層都會建構在較低層的公開 API 上,以驗證模組邊界,並視需求取代任何圖層。現在,讓我們從左下角開始分析這些圖層。

執行階段
這個模組提供 Compose 執行階段的基礎知識,例如 remembermutableStateOf}@Composable 註解和 SideEffect。如果您只需要撰寫 樹狀結構的樹狀結構功能 (而非 UI 功能),考慮直接在這個層建構。
UI
UI 層由多個模組 ( ui-text, ui-graphics, ui-tooling, 等)。這些模組實作 UI 工具包的基礎知識,例如 LayoutNodeModifier、輸入處理常式、自訂版面配置和繪圖。如果您只需要 UI 工具包的基本概念,可以考慮在這個層上建構內容。
Foundation
這個模組為 Compose UI 提供了跨平台設計的建構模塊。 人喜歡 RowColumn, LazyColumn, 可以協助辨識特定手勢等 讓您打造專屬設計系統。
材料
這個模組提供適用於 Compose UI 的質感設計系統實作程序,提供質感系統、樣式化元件、波浪圖示、圖示。在應用程式中使用 Material Design 時,請建構這個圖層。

設計原則

Jetpack Compose 的指導原則是提供可聚焦 (或組合) 的一系列細微功能,而非數個單體式元件。這個方法有許多優點。

控制

層級元件越高,您就越能執行更多操作,但會限制您能夠擁有的直接控制權。如果您需要更大的控制權,可以「下拉式選單」使用 較低層級的元件

舉例來說,如要讓元件的顏色能夠建立動畫,您可以使用 animateColorAsState API:

val color = animateColorAsState(if (condition) Color.Green else Color.Red)

不過,如果需要元件一律顯示為灰色,則您無法 如何透過這個 API 達成目標但您可以改為使用較低的層級 Animatable敬上 API:

val color = remember { Animatable(Color.Gray) }
LaunchedEffect(condition) {
    color.animateTo(if (condition) Color.Green else Color.Red)
}

較高層級的 animateColorAsState API 本身是在較低層級的 Animatable API 上建構。使用較低層級 API 較為複雜,但可控制更多設定。請選擇最符合需求的抽象層級。

自訂

從較小的建構區塊組成層級較高的元件,就能更輕鬆地自訂所需的元件。舉例來說,假設 Material 層提供了 Button實作

@Composable
fun Button(
    // …
    content: @Composable RowScope.() -> Unit
) {
    Surface(/* … */) {
        CompositionLocalProvider(/* … */) { // set LocalContentAlpha
            ProvideTextStyle(MaterialTheme.typography.button) {
                Row(
                    // …
                    content = content
                )
            }
        }
    }
}

Button 是由 4 個元件組合而成:

  1. 材質 Surface敬上 提供背景、形狀、點擊處理等。

  2. CompositionLocalProvider 會在啟用或停用按鈕時變更內容的 Alpha 值

  3. ProvideTextStyle 可設定要使用的預設文字樣式

  4. Row 會提供按鈕內容的預設版面配置政策

我們省略了部分參數和註解,以更清楚地顯示結構, 整個元件大約只有 40 行程式碼 組合這 4 個元件來實作按鈕。像 Button 這類元件則會注意自己所公開的參數,讓可以廣泛使用的自訂參數相輔相成,讓元件更容易使用。舉例來說,材料元件提供質感設計系統中指定的自訂項目,讓您輕鬆遵循質感設計原則。

不過,如果您想要自訂元件參數以外的自訂項目, 就可以「下拉式選單」物件等級和分支舉例來說,質感設計會指定按鈕應使用純色背景。如果您需要漸層背景,Button 參數不支援這個選項。在這種情況下,您可以使用 Material Button 實作做為參考資料,並建構自己的元件:

@Composable
fun GradientButton(
    // …
    background: List<Color>,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        // …
        modifier = modifier
            .clickable(onClick = {})
            .background(
                Brush.horizontalGradient(background)
            )
    ) {
        CompositionLocalProvider(/* … */) { // set material LocalContentAlpha
            ProvideTextStyle(MaterialTheme.typography.button) {
                content()
            }
        }
    }
}

上述實作項目繼續使用 Material 層的元件。 例如 Material Design 的 目前內容 Alpha 版 以及目前的文字樣式但是,它會將 Material Surface 替換為 Row 並設定樣式,達到想要的外觀。

如果您完全不想使用 Material Design 概念, 之後,您就能選擇單純使用基礎功能 包括

@Composable
fun BespokeButton(
    // …
    backgroundColor: Color,
    modifier: Modifier = Modifier,
    content: @Composable RowScope.() -> Unit
) {
    Row(
        // …
        modifier = modifier
            .clickable(onClick = {})
            .background(backgroundColor)
    ) {
        // No Material components used
        content()
    }
}

Jetpack Compose 會保留最高階元件的最簡單名稱。舉例來說,androidx.compose.material.Text 是以 androidx.compose.foundation.text.BasicText 為基礎。如此一來,如果想取代較高層級,則可透過自己的可偵測名稱提供自己的實作項目。

挑選合適的抽象層

Compose 的理念在於建構可重複使用的分層元件, 但 通常不會達到較低等級的建構模塊許多更高層級的元件不僅提供更多功能,而且通常會實作無障礙設計等最佳做法。

舉例來說,如要在自訂元件中新增手勢支援, 我們可以使用 Modifier.pointerInput敬上 但還有更多更高階的元件 會是更好的起點 Modifier.draggable, Modifier.scrollableModifier.swipeable

建議您以「最高層級」元件做為建構依據,以提供所需的功能,以享有其中包含的最佳做法。

瞭解詳情

詳情請參閱 Jetsnack 範例 例如建立自訂設計系統