Compose for Wear OS 程式碼研究室

1. 簡介

11ba5a682f1ffca3.png

Compose for Wear OS 的用法與 Jetpack Compose 相同,您可以根據先前的經驗建構適用於穿戴式裝置的應用程式。

Compose for Wear OS 內建 Material You 支援機制,可簡化及加速 UI 開發作業,協助您用較少的程式碼打造精美的應用程式。

在這個程式碼研究室中,我們希望您能對 Compose 有些基本瞭解,但不需要達到精通的境界。

您可以建立多種 Wear 專屬可組合內容 (包括簡易與複雜),最後,您可開始自行編寫適用於 Wear OS 的應用程式。立即開始!

學習目標

  • 與先前所用 Compose 的異同
  • 簡易可組合函式,以及在 Wear OS 上的運作方式
  • Wear OS 專屬的可組合函式
  • Wear OS 的 LazyColumn (ScalingLazyColumn)
  • Wear OS 的 Scaffold 版本

建構目標

您會建構一個簡單的應用程式,顯示可組合函式捲動式清單,這些可組合函式已針對 Wear OS 進行最佳化。

由於您使用 Scaffold,系統也會在頂端顯示弧形文字時間、暈影,以及沿著裝置側邊顯示的捲動指標。

完成本程式碼研究室後,您建立的應用程式會如下所示:

31cb08c0fa035400.gif

必要條件

2. 開始設定

在這個步驟中,您會設定環境並下載範例專案。

軟硬體需求

  • 最新的 Android Studio 穩定版
  • Wear OS 裝置或模擬器 (剛開始使用嗎?這裡有設定方式的說明)

下載程式碼

如果您已安裝 Git,只要執行下列指令即可複製這個存放區的程式碼。如要檢查 Git 是否已安裝完成,請在終端機或指令列中輸入 git --version,並確認該指令可正確執行。

git clone https://github.com/android/codelab-compose-for-wear-os.git
cd compose-for-wear-os

如果您沒有 Git,可以點選下方按鈕,下載這個程式碼研究室的所有程式碼:

您隨時都可變更工具列中的執行設定,在 Android Studio 中執行任一模組。

400c194c8948c952.png

在 Android Studio 中開啟專案

  1. 在「Welcome to Android Studio」視窗中,選取「61d0a4432ef6d396.png Open an Existing Project」
  2. 選取資料夾 [Download Location]
  3. Android Studio 匯入專案後,請測試是否能在 Wear OS 模擬器或實體裝置上執行 startfinished 模組。
  4. start 模組應如以下螢幕截圖所示。您會在該處執行所有工作。

c82b07a089099c4f.png

探索範例程式碼

  • build.gradle 包含基本的應用程式設定。這包括建立 Composable Wear OS 應用程式所需的依附元件。我們將探討 Jetpack Compose 與 Wear OS 版本有何相似與相異之處。
  • main > AndroidManifest.xml 包含建立 Wear OS 應用程式所需的元素。這與非 Compose 應用程式相同,且與行動應用程式類似,因此我們不會進行審查。
  • main > theme/ 資料夾包含 Compose 用於主題的 ColorTypeTheme 檔案。
  • main > MainActivity.kt 包含用於透過 Compose 建立應用程式的樣板。其中也包含我們應用程式的頂層可組合內容 (例如 ScaffoldScalingLazyList)。
  • main > ReusableComponents.kt 包含我們將要建立的大部分 Wear 特定可組合內容函式。我們將會在這個檔案中執行眾多作業。

3. 查看依附元件

您對 Wear 相關依附元件所做的變更,多半會位於架構層頂端 (下圖中以紅框標示處)。

d64d9c262a79271.png

這表示許多搭配 Jetpack Compose 使用的依附元件仍適用於 Wear OS 版本。舉例來說,您可以使用相同的使用者介面、執行階段、編譯器和動畫依附元件。

不過,先前使用的程式庫就不一定適用了,您必須採用適當的 Wear OS MaterialFoundationNavigation 程式庫。

您可透過下方的比較協助釐清差異:

Wear OS 依附元件(androidx.wear.*)

比較

標準依附元件 (androidx.*)

androidx.wear.compose:compose-material

而非

androidx.compose.material:material

androidx.wear.compose:compose-navigation

而非

androidx.navigation:navigation-compose

androidx.wear.compose:compose-foundation

除了

androidx.compose.foundation:foundation

androidx.wear.compose:compose-ui-tooling

加上

androidx.compose.ui:ui-tooling-preview

1. 開發人員可繼續使用如漣漪材質等其他材質相關程式庫,以及透過 Wear Compose Material 程式庫延伸的質感設計圖示。

開啟 build.gradle,在 start 模組中搜尋「TODO: Review Dependencies」。(這個步驟只是要查看依附元件,您將不會新增任何程式碼。)

start/build.gradle:

// TODO: Review Dependencies
// General Compose dependencies
implementation "androidx.activity:activity-compose:$activity_compose_version"
implementation "androidx.compose.ui:ui-tooling-preview:$compose_version"
implementation "androidx.compose.foundation:foundation:$compose_version"
implementation "androidx.compose.material:material-icons-extended:$compose_version"

// Compose for Wear OS Dependencies
implementation "androidx.wear.compose:compose-material:$wear_compose_version"

// Foundation is additive, so you can use the standard version in your Wear OS app.
implementation "androidx.wear.compose:compose-foundation:$wear_compose_version"

// Compose preview annotations for Wear OS.
implementation "androidx.wear.compose:compose-ui-tooling:$wear_compose_version"

您應會辨識眾多一般 Compose 依附元件,因此其不在我們的涵蓋範圍之列。

接著來看看 Wear OS 依附元件。

如前所述,系統只會納入 Wear OS 特定版本的 material (androidx.wear.compose:compose-material)。也就是說,您不會在專案中看到或包含 androidx.compose.material:material

請務必留意,您可以將其他材質程式庫與 Wear Material 搭配使用。我們實際上已在這個程式碼研究室中納入 androidx.compose.material:material-icons-extended,以實踐上述做法。

最後,我們納入適用於 Compose 的 Wear foundation 程式庫 (androidx.wear.compose:compose-foundation)。這是附加內容,方便您與先前所用的標準 foundation 搭配使用。事實上,您可能已經注意到我們在一般 Compose 依附元件中納入上述內容!

瞭解依附元件之後,我們來看看主要應用程式。

4. 查看 MainActivity

我們會在

start

模組中執行所有工作,因此請確認在模組中開啟每個檔案。

首先,請在 start 模組中開啟 MainActivity

這個相當簡單的類別延伸了 ComponentActivity,並使用 setContent { WearApp() } 來建立使用者介面。

根據您先前對 Compose 的瞭解,這對您來說應並不陌生。我們只是在設定使用者介面。

向下捲動至 WearApp() 可組合函式。在我們討論程式碼本身之前,您應該會看到許多 TODO 四散在程式碼中,每個都代表本程式碼研究室中的步驟。您可以暫時忽略這些資訊。

如下所示:

趣味 WearApp() 中的程式碼:

WearAppTheme {
    // TODO: Swap to ScalingLazyListState
    val listState = rememberLazyListState()

    /* *************************** Part 4: Wear OS Scaffold *************************** */
    // TODO (Start): Create a Scaffold (Wear Version)

        // Modifiers used by our Wear composables.
        val contentModifier = Modifier.fillMaxWidth().padding(bottom = 8.dp)
        val iconModifier = Modifier.size(24.dp).wrapContentSize(align = Alignment.Center)

        /* *************************** Part 3: ScalingLazyColumn *************************** */
        // TODO: Create a ScalingLazyColumn (Wear's version of LazyColumn)
        LazyColumn(
            modifier = Modifier.fillMaxSize(),
            contentPadding = PaddingValues(
                top = 32.dp,
                start = 8.dp,
                end = 8.dp,
                bottom = 32.dp
            ),
            verticalArrangement = Arrangement.Center,
            state = listState
        ) {

            // TODO: Remove item; for beginning only.
            item { StartOnlyTextComposables() }

            /* ******************* Part 1: Simple composables ******************* */
            item { ButtonExample(contentModifier, iconModifier) }
            item { TextExample(contentModifier) }
            item { CardExample(contentModifier, iconModifier) }

            /* ********************* Part 2: Wear unique composables ********************* */
            item { ChipExample(contentModifier, iconModifier) }
            item { ToggleChipExample(contentModifier) }
        }

    // TODO (End): Create a Scaffold (Wear Version)

}

首先請設定主題 WearAppTheme { }。操作方式與您先前撰寫的內容完全相同,亦即以顏色、字體排版和圖形來設定 MaterialTheme

不過,以 Wear OS 來說,我們通常建議使用預設的 Material Wear 形狀,這已一併針對圓形與非圓形裝置完成最佳化處理,因此若您深入瞭解 theme/Theme.kt,會發現我們並未覆寫形狀。

若有需要,您可開啟 theme/Theme.kt 進一步探索,不過一樣與之前相同。

接下來,我們將為要建構的 Wear 可組合函式建立一些修飾符,這樣就無需每次都指定。其主要是以內容為中心,並增加一些邊框間距。

與先前的做法相同,我們後續會建立 LazyColumn,用於產生內含許多項目的垂直捲動清單。

程式碼:

item { StartOnlyTextComposables() }

/* ******************* Part 1: Simple composables ******************* */
item { ButtonExample(contentModifier, iconModifier) }
item { TextExample(contentModifier) }
item { CardExample(contentModifier, iconModifier) }

/* ********************* Part 2: Wear unique composables ********************* */
item { ChipExample(contentModifier, iconModifier) }
item { ToggleChipExample(contentModifier) }

針對項目本身,僅有 StartOnlyTextComposables() 會產生任一使用者介面。(我們將會在整個程式碼研究室填入其餘部分)。

這些函式實際上是位於 ReusableComponents.kt 檔案,我們會於下節說明。

準備開始使用 Compose for Wear OS 吧!

5. 新增簡易的可組合函式

讓我們先來探討您可能已熟悉的三種可組合內容 (ButtonTextCard)。

首先,我們要移除 Hello World 可組合內容。

搜尋「TODO: Remove item」,然後清除留言和下一行:

步驟 1

// TODO: Remove item; for beginning only.
item { StartOnlyTextComposables() }

接著,讓我們來新增第一個可組合函式。

建立「按鈕」可組合函式

start 模組中開啟 ReusableComponents.kt 並搜尋「TODO: Create a Button Composable」,將目前的可組合內容方法替換為此程式碼。

步驟 2

// TODO: Create a Button Composable (with a Row to center)
@Composable
fun ButtonExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    Row(
        modifier = modifier,
        horizontalArrangement = Arrangement.Center
    ) {
        // Button
        Button(
            modifier = Modifier.size(ButtonDefaults.LargeButtonSize),
            onClick = { /* ... */ },
        ) {
            Icon(
                imageVector = Icons.Rounded.Phone,
                contentDescription = "triggers phone action",
                modifier = iconModifier
            )
        }
    }
}

ButtonExample() 可組合內容 (此程式碼所在函式) 現會產生置中按鈕。

讓我們來逐步瞭解程式碼。

Row 在此僅用於將 Button 可組合內容置中於圓形螢幕。實際做法是套用我們在 MainActivity 中建立的修飾符,並將其傳遞至此函式。之後在圓形螢幕上捲動時,我們會希望確保內容不會遭到截斷,這就是其會置中的原因所在。

接下來,我們要建立 Button 本身。程式碼與先前用於「按鈕」的程式碼相同,但本例中使用的是 ButtonDefault.LargeButtonSize。這些是針對 Wear OS 裝置最佳化的預設大小,因此請務必善加利用!

之後,我們會將點擊事件設為空白的 lambda。這些可組合內容在本範例中僅供示範用途,因此將無需派上用場。不過在實際應用程式中,我們會透過 ViewModel 等方式進行通訊,以便執行商業邏輯。

接著會在按鈕當中設定「圖示」。此程式碼與先前看過的 Icon 相同。我們也會從 androidx.compose.material:material-icons-extended 程式庫下載圖示,

最後,我們會設定先前針對「圖示」所設定的修飾符。

應用程式的執行畫面應該會像這樣:

c9b981101ae653db.png

您之前大概編寫過這個程式碼 (這樣很好),差別在於,現在取得的按鈕會針對 Wear OS 進行最佳化調整。

一切皆相當直覺,讓我們來看看另一個主題吧。

建立「文字」可組合函式

ReusableComponents.kt 中搜尋「TODO: Create a Text Composable」,並將目前的可組合方法替換為本程式碼。

步驟 3

// TODO: Create a Text Composable
@Composable
fun TextExample(modifier: Modifier = Modifier) {
    Text(
        modifier = modifier,
        textAlign = TextAlign.Center,
        color = MaterialTheme.colors.primary,
        text = stringResource(R.string.device_shape)
    )
}

建立 Text 可組合函式、為其設定修飾符、對齊文字、設定顏色,最後再透過字串資源設定文字本身。

Compose 開發人員應該會認為文字可組合函式相當眼熟,相關程式碼實際上與您先前使用的程式碼完全相同。

其外觀如下:

b33172e992d1ea3e.png

TextExample() 可組合函式 (程式碼的所在位置) 現在會產生用於設定主要材質顏色的 Text 可組合函式。

字串提取自 res/values/strings.xml 檔案。事實上,您查看 res/values 資料夾時,應該會看到兩個 strings.xml 資源檔案。

Wear OS 提供的字串資源適用於圓形和非圓形裝置。因此,如果在正方形的模擬器上執行這個字串,該字串會改變:

2e7b20dbfbd23350.png

到目前為止都很順利。我們來看看最後一個類似的可組合內容:Card

建立「卡片」可組合內容

ReusableComponents.kt 中搜尋「TODO: Create a Card」,並將目前的可組合方法替換為本程式碼。

步驟 4

// TODO: Create a Card (specifically, an AppCard) Composable
@Composable
fun CardExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    AppCard(
        modifier = modifier,
        appImage = {
            Icon(
                imageVector = Icons.Rounded.Message,
                contentDescription = "triggers open message action",
                modifier = iconModifier
            )
        },
        appName = { Text("Messages") },
        time = { Text("12m") },
        title = { Text("Kim Green") },
        onClick = { /* ... */ }
    ) {
        Text("On my way!")
    }
}

Wear 略有差異,其具有以下兩種主要的卡片:AppCardTitleCard

針對本範例,我們希望在資訊卡中使用 Icon,因此請使用 AppCard (TitleCard 的運算單元數量較少,詳情請參閱「資訊卡」指南)。

我們會建立 AppCard 可組合函式、設定其修飾符、新增 Icon、新增數個 Text 可組合參數 (分別用於資訊卡的不同處),最後在結尾處設定主要內容文字。

其外觀如下:

1fc761252ac5b466.png

您現在可能已經發現,這些可組合函式的 Compose 程式碼其實與之前使用的相同。這樣一來,您可以重複運用現有的所有知識!

讓我們看看一些新的可組合內容。

6. 新增 Wear 專屬可組合內容

我們將在本節中探索 ChipToggleChip 可組合內容。

建立「方塊」可組合函式

在材質指南中實際上已指定方塊,但在標準材質資料庫中並無實際的可組合函式。

方塊是一種快速、輕觸一下的動作,尤其適合螢幕空間有限的 Wear 裝置。

以下是 Chip 可組合函式的幾個不同版本,讓您瞭解可以建立的項目:

現在,我們就開始動手寫程式吧。

ReusableComponents.kt 中搜尋「TODO: Create a Chip」,並將目前的可組合方法替換為本程式碼。

步驟 5

// TODO: Create a Chip Composable
@Composable
fun ChipExample(
    modifier: Modifier = Modifier,
    iconModifier: Modifier = Modifier
) {
    Chip(
        modifier = modifier,
        onClick = { /* ... */ },
        label = {
            Text(
                text = "5 minute Meditation",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
        },
        icon = {
            Icon(
                imageVector = Icons.Rounded.SelfImprovement,
                contentDescription = "triggers meditation action",
                modifier = iconModifier
            )
        },
    )
}

Chip 可組合函式所用的參數中,有許多與您在其他可組合函式 (修飾符和 onClick) 內慣用的相同,因此我們無須查看這些參數。

其還使用標籤 (我們為其建立了一個 Text 可組合內容) 和圖示。

Icon 程式碼看起來應與您在其他可組合函式中看見的程式碼完全相同,但對於本程式碼,我們會從 androidx.compose.material:material-icons-extended 程式庫中提取 Self Improvement 圖示。

外觀如下 (請記得向下捲動):

d97151e85e9a1e03.png

一起來看看 Toggle 上的變化版本,即 ToggleChip 可組合函式。

建立 ToggleChip 可組合函式

ToggleChipChip 類似,但前者可讓使用者與圓形按鈕、切換按鈕或核取方塊互動。

ReusableComponents.kt 中搜尋「TODO: Create a ToggleChip」,並將目前的可組合方法替換為本程式碼。

步驟 6

// TODO: Create a ToggleChip Composable
@Composable
fun ToggleChipExample(modifier: Modifier = Modifier) {
    var checked by remember { mutableStateOf(true) }
    ToggleChip(
        modifier = modifier,
        checked = checked,
        toggleControl = {
            Switch(
                checked = checked,
                modifier = Modifier.semantics {
                    this.contentDescription = if (checked) "On" else "Off"
                }
            )
        },
        onCheckedChange = {
            checked = it
        },
        label = {
            Text(
                text = "Sound",
                maxLines = 1,
                overflow = TextOverflow.Ellipsis
            )
        }
    )
}

現在 ToggleChipExample() 可組合函式 (此程式碼的所在位置) 會產生採用切換按鈕 (而非核取方塊或圓形按鈕) 的 ToggleChip

首先,我們來建立 MutableState。由於主要目的是提供 UI 示範,讓您查看 Wear 提供哪些功能,因此我們未在其他函式中執行此操作。

在一般應用程式中,您可能會想傳入已勾選狀態和 lambda 來處理輕觸動作,因此可組合函式可能會是無狀態的 (詳情請參閱這裡)。

但在本例中,我們只想簡單呈現 ToggleChip 搭配可用切換按鈕的實際效果,因此即使未對狀態執行任何操作也無妨。

接下來,我們會設定修飾符、已勾選狀態和切換按鈕控制選項,以便產生所需的切換鈕。

接著我們會建立 lambda 來變更狀態,最後再使用 Text 可組合函式和一些基本參數來設定標籤。

其外觀如下:

ea1a76abd54877b.png

您現在已看過許多專用於 Wear OS 的可組合函式。如上文所述,程式碼多半都與您先前編寫的程式碼幾乎相同。

讓我們來看看一些更進階的資訊。

7. 遷移至 ScalingLazyColumn

您可能曾在行動應用程式中使用 LazyColumn 來產生垂直捲動清單。

由於圓形裝置的頂端和底部較小,因此可顯示項目的空間較少。基於以上原因,Wear OS 具有專屬的 LazyColumn 版本,以針對這些圓形裝置提供更妥善的支援。

ScalingLazyColumn 延伸 LazyColumn 以在螢幕頂端和底部支援縮放和透明度,讓使用者更容易讀取內容。

示範如下:

198ee8e8fa799f08.gif

請注意,當項目靠近中心時會放大至完整大小,然後在向外移動時會隨之縮小 (且會變得更為透明)。

以下是更具體的應用程式範例:

a5a83ab2e5d5230f.gif

我們發現這能提升可讀性。

您已瞭解到 ScalingLazyColumn 的實際運作,接下來讓我們開始轉換 LazyColumn

轉換為 ScalingLazyListState

MainActivity.kt 中搜尋「TODO: Swap to ScalingLazyListState」,然後將該留言和下一行替換為本程式碼。

步驟 7

// TODO: Swap to ScalingLazyListState
val listState = rememberScalingLazyListState()

這些名稱幾乎與「縮放」部分相同。就像 LazyListState 處理 LazyColumn 的狀態一樣,ScalingLazyListState 也會處理 ScalingLazyColumn 的狀態。

轉換為 ScalingLazyColumn

接著我們要更換為 ScalingLazyColumn

MainActivity.kt 中搜尋「TODO: Swap a ScalingLazyColumn」。首先,請將 LazyColumn 取代為 ScalingLazyColumn

然後一併移除 contentPaddingverticalArrangementScalingLazyColumn 已提供預設設定,並且能保證顯示更佳的預設視覺效果,因為大多數可視區域都會填滿清單項目。在大多數情況下,預設參數就足以應付;如果畫面頂端有標題,我們建議將其放進 ListHeader 中並列為第一個項目。否則,請考慮使用 itemIndexautoCentering 設為 0,這樣就能為第一個項目提供足夠的邊框間距。

步驟 8

// TODO: Swap a ScalingLazyColumn (Wear's version of LazyColumn)
ScalingLazyColumn(
    modifier = Modifier.fillMaxSize(),
    autoCentering = AutoCenteringParams(itemIndex = 0),
    state = listState

大功告成!其外觀如下:

5c25062081307944.png

您可以看到,畫面會在您捲動時縮放內容並調整頂端和底部的透明度,而這只要執行極少工作就能完成遷移!

當您上下移動冥想可組合內容時,就會確實留意到這點。

接著讓我們探討最後一個主題:Wear OS 的 Scaffold

8. 新增 Scaffold

Scaffold 提供版面配置結構,可協助您在一般模式下編排畫面,就像在行動裝置上顯示一樣。不過,有別於應用程式列、懸浮動作按鈕 (FAB)、導覽匣或其他行動裝置專用元素,Scaffold 支援四種包含以下頂層元件的 Wear 專用版面配置:時間、暈影、捲動/位置指標,以及頁面指標。

此外還能處理圓形與非圓形裝置。

這些元件如下所示:

TimeText

Vignette

PositionIndicator

PageIndicator

我們會詳細探討前三個元件,但先讓我們把 Scaffold 設定好。

新增 Scaffold

現在讓我們來新增 Scaffold 的樣板。

尋找「TODO (Start): Create a Scaffold (Wear Version)」,並在下方新增程式碼。

步驟 9

// TODO (Start): Create a Scaffold (Wear Version)
Scaffold(
    timeText = { },
    vignette = { },
    positionIndicator = { }
) {

我們將在後續步驟中依序說明每個參數。我們目前並未產生任何使用者介面。

接著,請務必在右方位置新增括弧。尋找「TODO (End): Create a Scaffold (Wear Version)」並加上括弧:

步驟 10

// TODO (End): Create a Scaffold (Wear Version)
}

請先執行。畫面應如下所示:

ff554156bbe03abb.png

請注意,加入 Scaffold 並不會改變實際運作方式,但開始導入元件後,運作方式就會改變。

首先介紹三個參數中的第一個參數:TimeText

TimeText

TimeText 會在背景中使用弧形文字,讓開發人員能夠輕鬆顯示時間,不僅不用放置可組合函式,也不用處理任何與時間相關的類別。

根據《Material 指南》建議,您應在應用程式的所有畫面頂端顯示時間,如下所示:

2a642b9ff3334e2a.png

新增 TimeText 其實非常簡單。

尋找「timeText = { },」並替換為以下程式碼:

步驟 11

timeText = {
    TimeText(modifier = Modifier.scrollAway(listState))
},

首先來建立 TimeText 可組合函式。我們可以新增額外參數,在時間的前後新增文字,但要力求簡潔。

使用可捲動元素 (例如清單) 建立 TimeText 時,如果使用者開始向上捲動項目清單,TimeText 應從檢視畫面中淡出。為此,我們新增了 Modifier.scrollAway,以便根據捲動狀態將 TimeText 垂直捲動進檢視畫面中 (反之亦然)。

請試著執行。您現在應該會看見時間,但只要捲動畫面,時間就會消失。

43e90952cbcce9b0.png

接著來探討 Vignette

新增暈影

每當顯示可捲動畫面時,Vignette 會模糊處理穿戴式裝置螢幕的頂緣和底緣。

開發人員可以根據用途,指定模糊處理頂端、底部或此兩者。

範例如下:

7e85451de59e1d0.png

裝置只有一個螢幕 (螢幕畫面可捲動),因此加上暈影可帶來更輕鬆的閱讀體驗。開始行動吧。

尋找「vignette = { },」並替換為以下程式碼:

步驟 12

vignette = {
    // Only show a Vignette for scrollable screens. This code lab only has one screen,
    // which is scrollable, so we show it all the time.
    Vignette(vignettePosition = VignettePosition.TopAndBottom)
},

參閱留言內容,進一步瞭解何時應該顯示暈影。在本範例中,畫面一律會顯示暈影,並模糊處理畫面頂端和底部。

f4679e75e295642c.png

您應該可以在畫面頂端或底部 (特別是紫色的可組合元素) 看見暈影的效果。

現在我們來完成 Scaffold 的最終參數 PositionIndicator

新增 PositionIndicator

PositionIndicator (亦稱「捲動指標」) 是畫面右側的指標,可讓您根據傳入的狀態物件類型,顯示目前的指標位置。在本範例中即是 ScalingLazyListState

範例如下:

ba42dce6b62e720f.png

您可能會好奇,為何位置指標需提高至 Scaffold 層級,而非 ScalingLazyColumn 層級。

由於螢幕為曲面,因此位置指標必須處於智慧手錶中央 (Scaffold),而非處於可視區域的中央 (ScalingLazyColumn),否則可能會遭到截斷。

舉例來說,在以下的應用程式中,我們假設「播放清單」可組合內容不屬於可捲動區域。位置指標置中於 ScalingLazyColumn,並未佔滿整個螢幕畫面。因此,您會發現指標的大多數內容都遭到截斷。

8018e75f709e25a0.png

不過,如果改為將位置指標置於整個可視介面中央 (透過 Scaffold 達成),畫面上就會清楚顯示該指標。

1a82be61163ead86.png

這表示使用 PositionIndicator 時,ScalingLazyListState (說明在捲動清單中的位置) 必須高於 Scaffold

若您觀察力敏銳,可能會注意到我們已提升 ScalingLazyListStateScaffold 上方來隱藏或顯示時間,因此就本範例而言,我們的工作已完成。

我們現已說明位置指標應位於 Scaffold 中的原因,接下來請將其新增至應用程式。

尋找「positionIndicator = { }」並替換為以下程式碼:

步驟 12

positionIndicator = {
    PositionIndicator(
        scalingLazyListState = listState
    )
}

此步驟相當簡單直覺,PositionIndicator 需要捲動狀態才能正常顯示,現在已可完成這項程序!

另外還具備貼心功能,可在使用者未捲動時自行隱藏。

我們使用的是 ScalingLazyListState,但 PositionIndicator 採用其他捲動選項,例如 ScrollStateLazyListState,甚至還可處理旋轉側邊按鈕或

旋轉邊框。如要查看所有選項,請查看每個版本的 KDocs

現在外觀看起來會像這樣:

cfcbd3003744a6d.png

請試著上下捲動。僅在捲動時才會看見捲動指標。

太棒了,您已完成大部分 Wear OS 可組合函式的 UI 演示程序!

9. 恭喜

恭喜!您已瞭解關於在 Wear OS 使用 Compose 的基本知識!

您現在可以重新應用所有 Compose 知識,打造精美的 Wear OS 應用程式!

後續步驟

查看其他 Wear OS 程式碼研究室:

其他資訊

意見回饋:

歡迎分享您使用 Compose for Wear OS 的經驗談,告訴我們您學會建構哪些內容!歡迎參與 Kotlin Slack #compose-wear 頻道的討論,並持續透過 Issue Tracker 提供意見回饋。

祝您編寫程式一切順利!