適用于 Wear OS 的 Compose 已推出了開發(fā)者預(yù)覽版,使用 Compose 構(gòu)建 Wear OS 應(yīng)用,不僅可以輕松遵循 Material You 指南,同時(shí)可以將 Compose 的優(yōu)點(diǎn)發(fā)揮出來。開箱即用,幫助開發(fā)者使用更少的代碼快速構(gòu)建出更精美的 Wear OS 應(yīng)用。本文將通過 Wear Compose 主要的可組合項(xiàng) (Composable) 來幫助您更好地了解如何使用 Compose 來進(jìn)行構(gòu)建。
移動(dòng)應(yīng)用往往需要針對(duì)多種不同的界面種類進(jìn)行開發(fā),通常情況下,承載應(yīng)用的主界面由 Fragment、Activity 和 View 構(gòu)成,而在 Compose 的世界中則是由可組合項(xiàng)構(gòu)成,作為開發(fā)者您需要了解并適應(yīng)這種變化。除此之外,您還要針對(duì)額外的通知界面進(jìn)行開發(fā),這意味著您需要在主應(yīng)用界面之外提醒用戶注意某些重要信息,或讓他們?cè)趩?dòng)主應(yīng)用后繼續(xù)完成剛剛執(zhí)行的操作,例如跟蹤跑步路線或者播放音樂。如果您使用了 Widget,也可以借助此類界面向用戶提供信息。
Wear OS 擁有多種界面,在打造完備的 Wear OS 應(yīng)用體驗(yàn)時(shí),需要您全部考慮:
疊加層 (Overlay) 與移動(dòng)應(yīng)用的主界面類似,之前由 Activity、View 和 Fragment 組成,現(xiàn)在由可組合項(xiàng)構(gòu)成,非常適合流程較長(zhǎng)或較為復(fù)雜的交互;
通知 (Notification) 界面同樣符合移動(dòng)應(yīng)用開發(fā)準(zhǔn)則;
復(fù)雜功能 (Complication) 可在表盤中提供信息便于用戶直接查看,用戶只需在表盤上輕點(diǎn)一下,Complication 即可打開相關(guān)聯(lián)的應(yīng)用,或執(zhí)行獨(dú)立操作,例如飲水記錄功能,記錄您一天用水杯喝水的次數(shù);
圖塊 (Tile) 提供了更多展示內(nèi)容的空間,用戶可在表盤上通過任意方向滑動(dòng),快速訪問信息、執(zhí)行操作。
多種界面
https://developer.android.google.cn/training/wearables/user-interfaces
疊加層 (Overlay)
https://developer.android.google.cn/training/wearables/overlays
本文我們將著重介紹 Overlay 界面,并快速演示幾項(xiàng) Wear 可組合項(xiàng),了解它們的工作原理及其與移動(dòng)平臺(tái)的相似之處。
添加依賴項(xiàng)
在使用 Wear Compose 之前,我們需要先確保已有正確的依賴項(xiàng),它同移動(dòng)版 Compose 略有不同。在移動(dòng)版上,主要使用的依賴項(xiàng)有 Material、Foundation、UI、Runtime 和 Compiler,您還可以選擇使用 Navigation 和 Animation 依賴。但在 Wear 中,您可以使用一樣的 UI 依賴項(xiàng),Runtime、Compiler 和 Animation 也都是相同的。此外,其他一些方面也都是相同的,比如工具和一些 Compose 設(shè)計(jì)理念,比如使用雙向數(shù)據(jù)流。
但還是有一些不同之處的,比如您需要使用 Wear Compose Material 替換 Material,單從技術(shù)上來說移動(dòng)版 Material 也是可以直接用的,但它并沒有針對(duì) Wear 的一些特性進(jìn)行優(yōu)化,類似的我們還推薦您使用 Wear Navigation 來替換 Navigation。
雖然我們建議直接使用 Wear Compose Material,但您仍然可以使用 Material Ripple 和 Material Icons Extended 等。在添加正確的 Wear 依賴項(xiàng)后,您就可以著手進(jìn)行開發(fā)了。
在 Wear Compose 文檔頁(yè)面查看依賴項(xiàng): https://developer.android.google.cn/jetpack/androidx/releases/wear-compose#declaring_dependencies
Wear OS Material 庫(kù)介紹
Compose Wear OS Material 庫(kù)提供了很多與移動(dòng)平臺(tái)上相同的可組合項(xiàng),您可以替換 Material 主題,并且自定義顏色、字體等,不同的是它們都針對(duì)手表進(jìn)行了優(yōu)化。接下來我們就為您介紹一些常用的可組合項(xiàng)。
Compose Wear OS Material 庫(kù)
https://developer.android.google.cn/reference/kotlin/androidx/wear/compose/material/package-summary.html
Material 主題
https://developer.android.google.cn/training/wearables/components/theme
Button
Button 屬于緊湊的界面元素,用戶可通過點(diǎn)按 Button 執(zhí)行操作或做出選擇。 https://developer.android.google.cn/training/wearables/components/buttons 通過如下代碼可輕松添加 Button,雖然樣式與移動(dòng)版不同,但代碼一樣。我們?cè)诖a里初始化了一個(gè) Button 可組合項(xiàng),然后聲明了一些參數(shù),它們被稱為 Modifier,通過 Modifier 可以更改很多屬性,比如這里的 onClick、same、enabled,若您還想為 Button 添加一個(gè)圖標(biāo),那就需要用到包含 painter、contentDescription 和 modifier 的 Icon 可組合項(xiàng):
Button( modifier = Modifier.size (ButtonDefaults.LargeButtonSize), onClick = {... }, enabled = enabledState) { Icon( painter = painterResource (id = R.drawable.ic_phone), contentDescription = "phone", modifier = Modifier .size(24. dp) .wrapContentSize(align = Alignment.Center), )}
△Button 可組合項(xiàng)代碼
通過上述代碼,我們可以創(chuàng)建精美小巧的 Button,顯示效果如下:
△Button 代碼效果
Card
Card 可針對(duì)單一主題的內(nèi)容和操作進(jìn)行呈現(xiàn),十分靈活。
https://developer.android.google.cn/training/wearables/components/cards
如圖左側(cè) Card 展示了一些圖標(biāo)和文字,中間界面只保留了文字,右側(cè)使用了一張圖片作為背景。
△Card 用例
在 Wear OS 中,主要有 AppCard 和 TitleCard 兩種 Card,TitleCard 更側(cè)重文字展示,本文我們將著重介紹 AppCard。如下示例代碼創(chuàng)建了一個(gè) AppCard,并相繼通過 Image、Text 和 Column 定制內(nèi)容:
AppCard( appImage = { Image(painter = painterResource(id = R.drawable.ic_message), …) }, appName = { Text ("Messages") }, time = { Text ("12m" ) }, title = { Text("Kim Green") }, onClick = { … }, body = { Column(modifier = Modifier.fillMaxWidth()) { Text("On my way!") } },)△Card 可組合項(xiàng)代碼 通過上述代碼,我們創(chuàng)建出了一個(gè)精美的 Card,顯示效果如下:
△Card代碼效果
如需獲得不同外觀的精美卡片顯示效果,僅需對(duì)代碼進(jìn)行輕微調(diào)整即可。 Chip Chip 旨在實(shí)現(xiàn)快捷的一鍵操作,對(duì)屏幕空間有限的 Wear 設(shè)備尤其有用,各種 Chip 變體也能讓您盡情揮灑創(chuàng)意: https://developer.android.google.cn/training/wearables/components/chips 下面是實(shí)現(xiàn) Chip 可組合項(xiàng)的代碼和實(shí)現(xiàn)效果,您會(huì)發(fā)現(xiàn)它十分易用,同上述的一些代碼也大致相似:
Chip( modifier = Modifier.align(Alignment.CenterHorizontally), onClick = { … }, enabled = enabledState, label = { Text( text = "1 minute Yoga", maxLines = 1, overflow = TextOverflow.Ellipsis ) }, icon = { Icon( painter = painterResource (id = R.drawable.ic_yoga), contentDescription= "yoga icon", modifier = Modifier .size(24.dp) .wrapContentSize(align = Alignment.Center), ) },)
△Chip可組合項(xiàng)代碼
△Chip 代碼效果
ToggleChip ToggleChip 和 Chip 類似,區(qū)別是用戶使用單選按鈕、切換開關(guān)、復(fù)選框: https://developer.android.google.cn/training/wearables/components/toggle-chips 如下所示 ToggleChip 用例:
△ToggleChip 用例
圖左展示,只需輕點(diǎn)即可開關(guān)聲音;圖右則對(duì) ToggleChip 進(jìn)行了拆分,提供了兩個(gè)不同的可點(diǎn)擊區(qū)域,通過右側(cè)按鈕可將其關(guān)閉,點(diǎn)擊左側(cè)可以進(jìn)入應(yīng)用以便對(duì)鬧鐘進(jìn)行編輯。其代碼大同小異:
ToggleChip( modifier = Modifier.height(32.dp) checked = checkedState, onCheckedChange = { … } label = { Text( text = "Sound", maxLines = 1, overflow = TextOverflow.Ellipsis ) })
△ToggleChip 代碼
△?ToggleChip 代碼效果
CurvedText 和 TimeText CurvedText 專門針對(duì)了圓形屏幕進(jìn)行了優(yōu)化,這對(duì)圓形設(shè)備來說非常重要,而 TimeText 是基于 CurvedText 所創(chuàng)建的可組合項(xiàng),它為您處理時(shí)間方面的所有文字顯示工作。
https://developer.android.google.cn/training/wearables/components/curved-text
如下代碼示例展示了如何創(chuàng)建 TimeText,并以 CurvedText 的方式進(jìn)行展示:
var textBeforeTime by rememberSaveable { mutableStateOf("ETA 99 hours") }// 首先創(chuàng)建在時(shí)間之前顯示的前綴字符串TimeText( // 創(chuàng)建 TimeText 可組合項(xiàng) leadingCurvedContent = { BasicCurvedText( text = textBeforeTime, style = TimeTextDefaults.timeCurvedTextStyle() ) },// 指定 leadingCurvedContent,在時(shí)間文本前顯示文字,以 CurvedText 的方式在曲面設(shè)備上展示。 leadingLinearContent = { Text( text = textBeforeTime, style = TimeTextDefaults.timeTextStyle() ) },// 指定 leadingLinearContent,在時(shí)間文本前顯示文字,常規(guī)顯示,適用于非曲面設(shè)備。)
△TimeText 代碼
通過上述代碼,我們可以看到時(shí)間文本在圓形屏幕的顯示效果如下:
△TimeText 顯示效果 ScalingLazyColumn 列表幾乎是每個(gè)應(yīng)用中都會(huì)用到的組件,它縱向展示了連續(xù)的界面元素。但由于 Wear OS 手表設(shè)備的屏幕頂部和底部空間都非常小,因此 Material Design 引入了新的 ScalingLazyColumn 來進(jìn)行縮放和透明度的展示,這樣有助于您在較小的空間內(nèi)查看列表的內(nèi)容。 △ScalingLazyColumn顯示效果 上圖展示了 ScalingLazyColumn 的效果,您可以看到隨著列表內(nèi)元素的滑入,當(dāng)列表的某一行靠近中心位置時(shí),會(huì)放大到完整尺寸,而隨著該元素的滑出,會(huì)變得越來越小 (并且變得更透明) 直至完全消失,這種效果十分有利于內(nèi)容的展示,內(nèi)容更易于用戶閱讀。 ScalingLazyColumn 底層是由 LazyColumn 實(shí)現(xiàn)的,它只會(huì)對(duì)即將要在屏幕上呈現(xiàn)的內(nèi)容進(jìn)行處理,這樣能夠高效地處理大量數(shù)據(jù),且能夠以縮放和透明效果進(jìn)行展示,因此它應(yīng)該成為 Wear OS 的默認(rèn)組件。 如上效果,ScalingLazyColumn 代碼示例如下:
val scalingLazyListState: ScalingLazyListState = rememberScalingLazyListState() ScalingLazyColumn( modifier = Modifier.fillMaxSize(), verticalArrangement = Arrangement.spacedBy(6.dp), state = scalingLazyListState,) { items(messageList.size) { message -> Card(...) {...} } item { Card(...) {...} }}
△ScalingLazyColumn 示例代碼
SwipeToDismissBox
這是大家十分熟悉的 Box 組件被視為界面中的一個(gè)容器,可在移動(dòng)端使用,但 Wear 中有專屬版本 SwipeToDismissBox,可用于您的布局,顧名思義它的功能是滑動(dòng)以關(guān)閉。在 Wear OS 中,主要的手勢(shì)就是滑動(dòng),通過使用 SwipeToDismissBox 向右滑動(dòng),就相當(dāng)于點(diǎn)擊了 "返回"按鈕。
val state = rememberSwipeToDismissBoxState() SwipeToDismissBox( state = state,){ isBackground -> if (isBackground) { Box(modifier = Modifier. fillMaxSize().background(MaterialTheme.colors.secondaryVariant)) } else { Column( modifier = Modifier.fillMaxSize().background(MaterialTheme.colors.primary), horizontalAlignment = Alignment.CenterHorizontally, verticalArrangement = Arrangement.Center, ){ Text ("Swipe to dismiss", color = MaterialTheme.colors.onPrimary) } }}△SwipeToDismissBox 示例代碼
在上述代碼中,我們?yōu)?SwipeToDismissBox 設(shè)置了 state 屬性,這一點(diǎn)和移動(dòng)端不同。通過傳遞的 state 獲取到 isBackground 回調(diào)值,它代表了此過程是否是滑動(dòng)返回,您可以根據(jù)不同的狀態(tài)展示不同的內(nèi)容。下圖是最終的呈現(xiàn)效果:
△SwipeToDismissBox 代碼效果
至此,我們介紹了一些 Wear OS 的可組合項(xiàng),若您對(duì)移動(dòng)端的可組合項(xiàng)開發(fā)有所了解,您可能會(huì)發(fā)現(xiàn)在 Wear OS 中開發(fā)基本是一樣的,換句話說,您之前學(xué)習(xí) Compose 時(shí)掌握的知識(shí)可以直接用于 Wear OS 開發(fā)。
使用 Scaffold
Scaffold 可讓您實(shí)現(xiàn)具有基本 Material Design 布局結(jié)構(gòu)的界面,它可為最常見的頂層 Material 組件 (例如 TopBar、BottomBar、FloatingActionButton 和 Drawer) 提供槽位。使用 Scaffold 時(shí),您可以確保這些組件能夠正確放置并協(xié)同工作。而在 Wear OS 中,它也有著專屬的版本,除了同移動(dòng)版相同的 content 組件之外,額外提供了以下三個(gè)主要組件:
△?Wear Scaffold 中的三個(gè)主要組件
TimeText: 可以將時(shí)間置于屏幕的頂部,我們已經(jīng)介紹過它,具體請(qǐng)參考上文中關(guān)于 TimeText 的部分;
Vignette: 可在屏幕周圍為您提供漂亮的暈影效果,如上圖中所示;
PositionIndicator: 也稱為滾動(dòng)指示器,是屏幕右側(cè)的指示符,用于根據(jù)您傳入的狀態(tài)對(duì)象類型顯示當(dāng)前指示符的位置。將它放置于 Scaffold 中是由于屏幕是弧形的,因此位置指示器需要位于表盤中央 (Scaffold),而不僅僅是在視口 (viewport) 中央。否則,指示器可能會(huì)被截?cái)唷?/p>
Scaffold 設(shè)計(jì)
△Scaffold 設(shè)計(jì)層級(jí)
在進(jìn)行 Scaffold 的設(shè)計(jì)時(shí),請(qǐng)參考上圖中的層級(jí)順序進(jìn)行考慮,首先要做的是對(duì) App 進(jìn)行設(shè)置,其次是設(shè)置 MaterialTheme 來自定義一些應(yīng)用的外觀和風(fēng)格,緊接著是考慮如何放置 Scaffold,最后才是對(duì) Content 的定義。這個(gè)順序同在移動(dòng)端是一樣的,先考慮設(shè)置 Theme,再到 Scaffold,接下來看一下如何編寫代碼:
// positionIndicator 在 Content 之外,因此要將 state 提升到 Scaffold 之上的級(jí)別val scalingLazyListState: ScalingLazyListState = rememberScalingLazyListState() MaterialTheme { Scaffold( modifier = Modifier.fillMaxSize(), timeText = {...}, vignette = { Vignette (vignettePosition = VignettePosition.TopAndBottom) }, positionIndicator = { // 通過查看 state 來判斷是否處于滾動(dòng)狀態(tài),若否,則不會(huì)進(jìn)行展示 if (scalingLazyListState.isScrollInProgress) { // PositionIndicator 需要用到 state,這也是我們從 LazyColumn 提升狀態(tài)的主要原因 PositionIndicator(scalingLazyListState = scalingLazyListState) } } ) { // 設(shè)置 content … }}△Scaffold 示例代碼
上述代碼中,由于 positionIndicator 位于 content 之外,因此要將 state 提升到 Scaffold 之上的級(jí)別,來避免它在屏幕中被截?cái)?。而在滾動(dòng)時(shí),可以通過檢查滾動(dòng)狀態(tài),通過隱藏時(shí)間顯示來為屏幕留出更多的空間,還可以根據(jù)狀態(tài)來關(guān)閉或打開 vignette 效果。positionIndicator 支持多種滾動(dòng)選項(xiàng),本例中我們使用了 scalingLazyListState,還可以使用很多效果炫酷的其他選項(xiàng),具體請(qǐng)參考相關(guān)文檔。而關(guān)于 modifier 和 TimeText 想必不用過多介紹了,而 vignette 的設(shè)置其實(shí)也很簡(jiǎn)單。
Navigation
在本文一開始就提到您需要使用 Wear Navigation 依賴項(xiàng)來替換 Navigation,這里再次強(qiáng)調(diào)一下,從技術(shù)層面來說您仍可使用 Navigation,但是可能會(huì)遇到各種問題,所以還是建議您直接使用已針對(duì) Wear 優(yōu)化的 Wear Navigation。
△Navigation 設(shè)計(jì)
Wear Navigation
https://developer.android.google.cn/training/wearables/design/navigation
關(guān)于 Navigation 的設(shè)計(jì),同 Scaffold 大致相同,采用了和移動(dòng)版相同的設(shè)計(jì),只是在 Scaffold 之下和 Content 之上增加了 SwipeDismissableNavHost,顧名思義該組件支持滑出操作,您可以直接使用與移動(dòng)應(yīng)用開發(fā)相同的知識(shí)來編寫代碼。
MaterialTheme { Scaffold(...){ val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = Screen.MainScreen.route ) { composable(route = Screen.MainScreen.route){ MyListScreen(...) } composable(route = Screen.DetailsScreen. route + "/{$ID}", ...) { MyDetailScreen(...) } } }}△Navigation 示例代碼 在上述代碼中,MaterialTheme 和 Scaffold 與之前一樣,但我們創(chuàng)建了一個(gè) navController,并使用了 SwipeDismissable 版本的 rememberSwipeDismissableNavController,名稱非常拗口,但是很容易理解它的功能。然后使用了 SwipeDismissableNavHost 將 startDestination 及其路徑傳遞到控制器中,再設(shè)置主屏幕內(nèi)容即可。您會(huì)發(fā)現(xiàn)代碼基本上同移動(dòng)端相同,非常便于理解。
總結(jié)
在 Wear OS 中,請(qǐng)確保使用合適的依賴項(xiàng),替換 Material 并添加 Foundation 依賴,如果使用的是 Navigation 同樣也要進(jìn)行替換。另外,所有 Compose 構(gòu)建方面的知識(shí)都可以直接應(yīng)用于 Wear Compose 中,用移動(dòng)端的開發(fā)經(jīng)驗(yàn)助您快速構(gòu)建精美的 Wear 界面。
原文標(biāo)題:使用 Compose 構(gòu)建 Wear OS 應(yīng)用
文章出處:【微信公眾號(hào):谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
-
移動(dòng)應(yīng)用
+關(guān)注
關(guān)注
0文章
64瀏覽量
15532 -
界面
+關(guān)注
關(guān)注
0文章
59瀏覽量
15620 -
代碼
+關(guān)注
關(guān)注
30文章
4779瀏覽量
68521
原文標(biāo)題:使用 Compose 構(gòu)建 Wear OS 應(yīng)用
文章出處:【微信號(hào):Google_Developers,微信公眾號(hào):谷歌開發(fā)者】歡迎添加關(guān)注!文章轉(zhuǎn)載請(qǐng)注明出處。
發(fā)布評(píng)論請(qǐng)先 登錄
相關(guān)推薦
評(píng)論