1. Giới thiệu
Compose cho Wear OS giúp bạn áp dụng kiến thức đã học về cách tạo ứng dụng bằng Jetpack Compose vào thiết bị đeo.
Với tính năng hỗ trợ tích hợp sẵn dành cho Material Design, Compose cho Wear OS sẽ tinh giản và đẩy nhanh quá trình phát triển giao diện người dùng, đồng thời giúp bạn tạo các ứng dụng đẹp mắt mà không cần lập trình nhiều.
Đối với lớp học lập trình này, chúng tôi mong rằng bạn sẽ có được một số kiến thức về Compose, mặc dù không nhất thiết phải thành thạo.
Chúng ta sẽ dùng Horologist, một dự án nguồn mở được xây dựng dựa trên Jetpack Compose giúp nhà phát triển đẩy nhanh quá trình phát triển ứng dụng.
Bạn sẽ tạo một số thành phần kết hợp dành riêng cho Wear (cả đơn giản lẫn phức tạp) và cuối cùng, bạn có thể bắt đầu viết ứng dụng của riêng mình dành cho Wear OS. Hãy bắt đầu!
Kiến thức bạn sẽ học được
- Những điểm tương đồng/khác biệt giữa trải nghiệm trước đây của bạn với Compose
- Các thành phần kết hợp đơn giản và cách các thành phần này hoạt động trên Wear OS
- Các thành phần kết hợp dành riêng cho Wear OS
LazyColumn
của Wear OS (ScalingLazyColumn
)- Phiên bản
Scaffold
của Wear OS
Sản phẩm bạn sẽ tạo ra
Bạn sẽ tạo một ứng dụng đơn giản cho thấy một danh sách dạng cuộn bao gồm các thành phần kết hợp đã tối ưu hoá dành cho Wear OS.
Vì sẽ sử dụng Scaffold
, nên bạn cũng sẽ tạo một đoạn văn bản cong cho thấy thời gian ở trên cùng, hiệu ứng làm mờ (vignette) và cuối cùng là chỉ báo cuộn ở cạnh thiết bị.
Sau đây là hình minh hoạ sản phẩm của bạn sau khi hoàn tất lớp học lập trình này:
Điều kiện tiên quyết
- Hiểu biết cơ bản về hoạt động phát triển Android
- Kiến thức cơ bản về Kotlin
- Kiến thức cơ bản về Compose
2. Bắt đầu thiết lập
Ở bước này, bạn sẽ thiết lập môi trường và tải dự án bắt đầu xuống.
Bạn cần có
- Phiên bản ổn định mới nhất của Android Studio
- Thiết bị hoặc trình mô phỏng Wear OS (Bạn còn bỡ ngỡ? Đây là cách thiết lập.)
Tải mã xuống
Nếu đã cài đặt git, bạn chỉ cần chạy lệnh dưới đây để sao chép mã từ kho lưu trữ này. Để kiểm tra xem git đã được cài đặt hay chưa, hãy nhập git --version
vào dòng lệnh hoặc cửa sổ dòng lệnh và xác minh rằng git thực thi đúng cách.
git clone https://github.com/android/codelab-compose-for-wear-os.git cd codelab-compose-for-wear-os
Nếu không có git, bạn có thể nhấp vào nút sau đây để tải tất cả mã dành cho lớp học lập trình này:
Bạn có thể chạy một trong hai mô-đun trong Android Studio bất cứ lúc nào bằng cách thay đổi cấu hình chạy trên thanh công cụ.
Mở dự án trong Android Studio
- Trên cửa sổ Welcome to Android Studio (Chào mừng bạn đến với Android Studio), hãy chọn biểu tượng Open an Existing Project (Mở một dự án hiện có).
- Chọn thư mục
[Download Location]
- Khi Android Studio đã nhập dự án, hãy kiểm tra để chắc chắn rằng bạn có thể chạy các mô-đun
start
vàfinished
trên một trình mô phỏng hoặc thiết bị Wear OS thực. - Mô-đun
start
sẽ có dạng như ảnh chụp màn hình dưới đây. Đây là nơi bạn sẽ làm mọi việc.
Khám phá mã bắt đầu
build.gradle
chứa cấu hình ứng dụng cơ bản. build.gradle bao gồm các phần phụ thuộc cần thiết để tạo một ứng dụng Wear OS có thành phần kết hợp (composable). Chúng ta sẽ thảo luận về điểm giống và khác nhau giữa Jetpack Compose và phiên bản dành cho Wear OS.main > AndroidManifest.xml
bao gồm các phần tử cần thiết để tạo một ứng dụng Wear OS. Ứng dụng không phải Compose cũng tương tự và giống với ứng dụng di động, vì vậy chúng ta sẽ không xem xét đến.- Thư mục
main > theme/
chứa các tệpColor
,Type
vàTheme
mà Compose dùng cho giao diện (theme). main > MainActivity.kt
có chứa mẫu tạo sẵn để tạo ứng dụng bằng Compose. MainActivity.kt cũng chứa các thành phần kết hợp cấp cao nhất (nhưScaffold
vàScalingLazyList
) cho ứng dụng của chúng ta.main > ReusableComponents.kt
chứa các hàm cho hầu hết thành phần kết hợp dành riêng cho Wear mà chúng ta sẽ tạo. Chúng ta sẽ làm rất nhiều việc trong tệp này.
3. Xem xét phần phụ thuộc
Hầu hết thay đổi về phần phụ thuộc liên quan đến Wear mà bạn thực hiện sẽ nằm ở các lớp kiến trúc (architectural layer) cấp cao (đánh dấu bằng màu đỏ trong hình dưới đây).
Tức là nhiều phần phụ thuộc mà bạn từng sử dụng trong Jetpack Compose sẽ không thay đổi khi nhắm đến Wear OS. Ví dụ: các phần phụ thuộc UI (Giao diện người dùng), Runtime (Thời gian chạy), Compiler (Trình biên dịch) và Animation (Ảnh động) sẽ vẫn giữ nguyên.
Tuy nhiên, bạn sẽ cần phải sử dụng các thư viện Wear OS Material (Chất liệu), Foundation (Nền tảng) và Navigation (Điều hướng) phù hợp. Các thư viện này khác với các thư viện bạn từng sử dụng.
Dưới đây là phần so sánh để giúp làm rõ sự khác biệt:
Phần phụ thuộc Wear OS(androidx.wear.*) | So sánh | Phần phụ thuộc tiêu chuẩn(androidx.*) |
thay cho | androidx.compose.material:material ₁ | |
thay cho | androidx.navigation:navigation-compose | |
bổ sung cho | androidx.compose.foundation:foundation | |
bổ sung cho | androidx.compose.ui:ui-tooling-preview |
1. Nhà phát triển có thể tiếp tục sử dụng các thư viện Material khác (chẳng hạn như thư viện Material ripple và biểu tượng Material mở rộng) trong thư viện Wear Compose Material.
Mở build.gradle
, tìm kiếm "TODO: Review Dependencies
" trong mô-đun start
của bạn. (Bước này chỉ để xem xét phần phụ thuộc và bạn sẽ không thêm mã nào.)
start/build.gradle:
def composeBom = platform(libs.androidx.compose.bom)
// General compose dependencies
implementation composeBom
implementation libs.androidx.activity.compose
implementation libs.compose.ui.tooling.preview
implementation(libs.androidx.material.icons.extended)
// Compose for Wear OS Dependencies
implementation libs.wear.compose.material
// Foundation is additive, so you can use the mobile version in your Wear OS app.
implementation libs.wear.compose.foundation
// Compose preview annotations for Wear OS.
implementation(libs.androidx.compose.ui.tooling)
debugImplementation libs.compose.ui.tooling
debugImplementation libs.androidx.ui.test.manifest
debugImplementation composeBom
Bạn sẽ nhận ra nhiều phần phụ thuộc chung của Compose, vì vậy chúng ta sẽ không trình bày các phần đó.
Hãy chuyển đến các phần phụ thuộc dành cho Wear OS.
Như đã nêu trước đó, chỉ phiên bản dành riêng cho Wear OS của material
(androidx.wear.compose:compose-material
) mới được đưa vào. Nghĩa là, bạn sẽ không thấy hoặc không đưa androidx.compose.material:material
vào dự án.
Quan trọng là bạn phải nhớ rằng có thể sử dụng các thư viện Material khác cho Wear Material. Chúng ta sẽ làm như vậy trong lớp học lập trình này bằng cách đưa androidx.compose.material:material-icons-extended
vào dự án.
Cuối cùng, chúng ta đưa thư viện Wear foundation
vào Compose (androidx.wear.compose:compose-foundation
) . Đây là tính năng bổ sung, vì vậy, bạn có thể sử dụng thư viện này với foundation
tiêu chuẩn bạn từng sử dụng. Trên thực tế, có thể bạn đã nhận ra rằng chúng ta đã đưa thư viện này vào các phần phụ thuộc chung trong Compose!
Giờ đây khi đã hiểu các phần phụ thuộc, hãy cùng xem ứng dụng chính.
4. Xem xét MainActivity
Chúng ta sẽ thực hiện mọi công việc trên
start
mô-đun, nên hãy đảm bảo rằng mọi tệp bạn mở đều nằm trong đó.
Hãy bắt đầu bằng cách mở MainActivity
trong mô-đun start
.
Đây là một lớp (class) khá đơn giản, mở rộng ComponentActivity
và sử dụng setContent { WearApp() }
để tạo giao diện người dùng.
Dựa trên kiến thức trước đây của bạn về Compose, có lẽ việc này không có gì lạ. Chúng ta chỉ đang thiết lập giao diện người dùng.
Cuộn xuống hàm thành phần kết hợp WearApp()
. Trước khi chúng ta nói về đoạn mã đó, bạn sẽ thấy rất nhiều mục "TODO" ("CẦN LÀM") rải rác trong suốt đoạn mã. Mỗi mục này đại diện cho các bước trong lớp học lập trình này. Hiện giờ, bạn có thể bỏ qua.
Đoạn mã sẽ trông giống như sau:
Mã thú vị trong WearApp():
WearAppTheme {
/* *************************** Part 4: Wear OS Scaffold *************************** */
// TODO (Start): Create a AppScaffold (Wear Version)
// TODO: Swap to ScalingLazyColumnState
val listState = rememberLazyListState()
/* *************************** Part 4: Wear OS Scaffold *************************** */
// TODO (Start): Create a ScreenScaffold (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: Swap 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 ScreenScaffold (Wear Version)
// TODO (End): Create a AppScaffold (Wear Version)
}
Chúng ta bắt đầu bằng việc thiết lập theme (chủ đề), WearAppTheme { }
. Việc này giống hệt như cách bạn từng viết mã, tức là bạn thiết lập một MaterialTheme
cho màu sắc, kiểu chữ và hình dạng.
Tuy nhiên, trong trường hợp của Wear OS, chúng tôi thường đề xuất sử dụng các hình dạng Material Wear mặc định được tối ưu hoá cho thiết bị hình tròn. Vì vậy, nếu tìm hiểu kỹ về theme/Theme.kt
của chúng tôi, bạn có thể thấy chúng tôi không ghi đè các hình dạng.
Nếu muốn, bạn có thể mở theme/Theme.kt
để khám phá thêm, nhưng xin nhắc lại, tệp này vẫn giống như trên điện thoại.
Tiếp theo, chúng ta sẽ tạo một số Đối tượng sửa đổi cho các thành phần kết hợp Wear mà chúng ta định tạo. Như vậy, chúng ta không cần chỉ định những đối tượng sửa đổi đó mỗi lần. Chủ yếu là việc căn giữa cho nội dung và thêm một số khoảng đệm.
Sau đó, chúng ta sẽ tạo một LazyColumn
dùng để tạo một danh sách cuộn theo chiều dọc dành cho nhiều mục (giống như bạn từng làm trước đây).
Mã:
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) }
Đối với các mục này, chỉ có StartOnlyTextComposables()
tạo ra giao diện người dùng. (Chúng ta sẽ điền phần còn lại trong suốt lớp học lập trình này.)
Các hàm này thực ra nằm trong tệp ReusableComponents.kt
mà chúng ta sẽ xem trong phần tiếp theo.
Hãy bắt đầu dùng Compose for Wear OS!
5. Thêm các thành phần kết hợp đơn giản
Chúng ta sẽ bắt đầu với 3 thành phần kết hợp (Button
, Text
và Card
) mà bạn có thể đã quen thuộc.
Trước tiên, chúng ta sẽ xoá thành phần kết hợp "hello world" ("xin chào thế giới").
Tìm "TODO: Remove item
" rồi xoá cả nhận xét (comment) và dòng bên dưới:
Bước 1
// TODO: Remove item; for beginning only.
item { StartOnlyTextComposables() }
Tiếp theo, hãy thêm thành phần kết hợp đầu tiên.
Tạo thành phần kết hợp Button
Mở ReusableComponents.kt
trong mô-đun start
rồi tìm "TODO: Create a Button Composable
" và thay thế phương pháp thành phần kết hợp hiện tại bằng mã này.
Bước 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
)
}
}
}
Hàm thành phần kết hợp ButtonExample()
(nơi mã này tồn tại) giờ đây sẽ tạo ra một nút được căn giữa.
Hãy cùng xem qua mã này.
Row
chỉ được dùng ở đây để căn giữa thành phần kết hợp Button
trên màn hình tròn. Bạn có thể thấy rằng chúng ta đang làm việc đó bằng cách áp dụng đối tượng sửa đổi đã tạo trong MainActivity
rồi chuyển đối tượng sửa đổi đó vào hàm này. Sau này, khi cuộn trên một màn hình tròn, chúng ta muốn đảm bảo rằng nội dung không bị cắt bỏ (đó là lý do nội dung đó được căn giữa).
Tiếp theo, chúng ta sẽ tạo riêng Button
. Mã này giống như mã dùng cho Button trước đó, nhưng trong trường hợp này, chúng ta sử dụng ButtonDefault.LargeButtonSize
. Đây là các kích thước đặt sẵn được tối ưu hoá dành cho các thiết bị Wear OS, vì vậy, hãy đảm bảo rằng bạn sử dụng đúng các kích thước này!
Sau đó, chúng ta đặt sự kiện nhấp vào một lambda trống. Trong trường hợp này, các thành phần kết hợp này chỉ để minh hoạ, vì vậy chúng ta không cần làm điều đó. Tuy nhiên, trong ứng dụng thực tế, có thể chúng ta sẽ giao tiếp với một thành phần, chẳng hạn như ViewModel, để thực hiện logic kinh doanh.
Sau đó, chúng ta đặt một Icon (Biểu tượng) bên trong nút. Mã này giống như mã bạn đã từng thấy đối với Icon
trước đó. Chúng ta cũng đang lấy biểu tượng qua thư viện androidx.compose.material:material-icons-extended
.
Cuối cùng, chúng ta đặt đối tượng sửa đổi đã đặt trước đó cho các biểu tượng.
Nếu chạy ứng dụng, bạn sẽ thấy như sau:
Đây là mã có thể bạn từng viết (nếu vậy thì thật tuyệt). Điểm khác biệt là giờ đây bạn có thể sử dụng nút được tối ưu hoá cho Wear OS.
Khá đơn giản, hãy xem qua một phần khác.
Tạo thành phần kết hợp Text
Trong ReusableComponents.kt
, hãy tìm "TODO: Create a Text Composable
" rồi thay thế phương thức thành phần kết hợp hiện tại bằng mã này.
Bước 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)
)
}
Chúng ta tạo thành phần kết hợp Text
, đặt đối tượng sửa đổi, căn chỉnh văn bản, đặt màu sắc và cuối cùng là tách riêng văn bản với tài nguyên chuỗi.
Các thành phần kết hợp văn bản (text) có thể trông rất quen thuộc với nhà phát triển sử dụng Compose và mã này thực sự giống với mã bạn từng dùng trước đây.
Hãy cùng xem:
Hàm thành phần kết hợp TextExample()
(nơi chúng ta đặt mã của mình) nay tạo ra thành phần kết hợp văn bản (Text composable) trong màu material chính. Chuỗi này được lấy từ tệp res/values/strings.xml
của chúng ta.
Đến giờ thì mọi thứ vẫn ổn! Hãy xem thành phần kết hợp tương tự gần đây nhất của chúng ta, Card
.
Tạo thành phần kết hợp Card
Trong ReusableComponents.kt
, hãy tìm "TODO: Create a Card
" rồi thay thế phương thức thành phần kết hợp hiện tại bằng mã này.
Bước 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 có một chút khác biệt ở chỗ chúng ta có hai thẻ (card) chính là AppCard
và TitleCard
.
Trong trường hợp này, chúng ta muốn sử dụng Icon
trong thẻ, vì vậy, chúng ta sẽ sử dụng AppCard
. (TitleCard
có ít chỗ hơn, hãy xem hướng dẫn về Thẻ để biết thêm thông tin.)
Chúng ta tạo thành phần kết hợp AppCard
, đặt đối tượng sửa đổi, thêm Icon
, thêm vài tham số thành phần kết hợp Text
(mỗi tham số cho một khoảng trống riêng trên thẻ) và cuối cùng là đặt văn bản nội dung chính ở cuối.
Hãy cùng xem:
Tại thời điểm này, có lẽ bạn nhận ra đối với các thành phần kết hợp này, mã Compose gần như giống với cách bạn từng sử dụng trước đây. Điều này tuyệt phải không? Bạn có thể sử dụng lại tất cả kiến thức mình đã có!
Hãy xem xét một số thành phần kết hợp mới.
6. Thêm các thành phần kết hợp độc đáo cho Wear
Trong phần này, chúng ta sẽ khám phá các thành phần kết hợp Chip
và ToggleChip
.
Tạo thành phần kết hợp Chip
Chip thực sự được đề cập đến trong hướng dẫn về material, nhưng không có hàm thành phần kết hợp thực tế trong thư viện material tiêu chuẩn.
Đây được coi là một thao tác nhanh, chỉ với một lần nhấn. Điều này đặc biệt phù hợp với thiết bị Wear có màn hình bị hạn chế.
Sau đây là một vài biến thể của hàm có khả năng kết hợp Chip
để gợi ý cho bạn về những gì bạn có thể tạo:
Hãy viết một vài mã
Trong ReusableComponents.kt
, hãy tìm "TODO: Create a Chip
" rồi thay thế phương thức thành phần kết hợp hiện tại bằng mã này.
Bước 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
)
},
)
}
Thành phần kết hợp Chip
sử dụng nhiều tham số giống như các tham số bạn từng dùng với các thành phần kết hợp khác (đối tượng sửa đổi và onClick
). Do đó, chúng ta không cần xem xét các tham số đó.
Thành phần kết hợp này cũng cần có nhãn (mà chúng ta sẽ thực hiện bằng cách tạo thành phần kết hợp Text
) và biểu tượng.
Mã Icon
phải giống hoàn toàn với mã mà bạn thấy trong các thành phần kết hợp khác. Tuy nhiên, đối với mã này, chúng ta đang kéo biểu tượng Self Improvement
từ thư viện androidx.compose.material:material-icons-extended
.
Hãy xem thành quả trông như thế nào (hãy nhớ cuộn xuống):
Được rồi, hãy xem biến thể trên Toggle
, thành phần kết hợp ToggleChip
.
Tạo thành phần kết hợp ToggleChip
ToggleChip
chỉ giống như một Chip
nhưng cho phép người dùng tương tác với nút chọn, nút bật/tắt hoặc hộp đánh dấu.
Trong ReusableComponents.kt
, hãy tìm "TODO: Create a ToggleChip
" rồi thay thế phương thức thành phần kết hợp hiện tại bằng mã này.
Bước 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
)
}
)
}
Bây giờ, hàm có khả năng kết hợp ToggleChipExample()
(nơi mã này tồn tại) tạo ra một ToggleChip
sử dụng nút bật/tắt (thay vì hộp đánh dấu hoặc nút chọn).
Trước tiên, chúng ta sẽ tạo một MutableState
. Chúng ta chưa thực hiện việc này trong các hàm khác vì chúng ta chủ yếu làm việc trên bản minh hoạ giao diện người dùng để bạn có thể xem các tính năng của Wear.
Trong một ứng dụng thông thường, bạn nên truyền vào trạng thái đã đánh dấu và lambda để xử lý thao tác nhấn, do đó thành phần kết hợp có thể không có trạng thái (xem thêm thông tin tại đây).
Trong trường hợp này, chúng ta chỉ đơn giản là cho thấy ToggleChip
trông như thế nào khi dùng nút bật/tắt đang hoạt động (mặc dù chúng ta không làm gì với trạng thái này).
Tiếp theo, chúng ta đặt đối tượng sửa đổi, trạng thái đánh dấu và chế độ điều khiển bật/tắt để tạo nút chuyển như mong muốn.
Sau đó, chúng ta tạo một lambda để thay đổi trạng thái và cuối cùng đặt nhãn bằng thành phần kết hợp Text
(và một số tham số cơ bản).
Hãy cùng xem:
Hiện tại, bạn đã thấy nhiều thành phần kết hợp dành riêng cho Wear OS và như đã nói trước đây, hầu hết mã gần giống như những mã bạn từng viết trước đây.
Hãy xem xét khía cạnh nào đó nâng cao hơn một chút.
7. Di chuyển sang ScalingLazyColumn
Có thể bạn đã sử dụng LazyColumn
trong ứng dụng di động để tạo danh sách cuộn theo chiều dọc.
Vì thiết bị hình tròn nhỏ hơn ở phía trên cùng và dưới cùng nên không gian để hiện các mục sẽ nhỏ hơn. Do đó, Wear OS có phiên bản LazyColumn
riêng để hỗ trợ hiệu quả hơn cho các thiết bị hình tròn như vậy.
ScalingLazyColumn
mở rộng LazyColumn
để hỗ trợ cả tính năng chia tỷ lệ và độ trong suốt ở đầu và cuối màn hình để người dùng có thể đọc được nội dung dễ dàng hơn.
Sau đây là một bản minh hoạ:
Hãy lưu ý cách một mục mở rộng ra kích thước đầy đủ khi tiến lại gần trung tâm và giảm kích thước khi di chuyển đi (cùng với việc tăng độ trong suốt).
Sau đây là ví dụ cụ thể hơn trong một ứng dụng:
Chúng ta thấy điều này thực sự khiến giao diện dễ đọc hơn.
Sau khi bạn thấy ScalingLazyColumn
hoạt động, hãy bắt đầu chuyển đổi LazyColumn
.
Chúng ta sẽ dùng Horologist ScalingLazyColumn để đảm bảo các mục trong danh sách có khoảng đệm chính xác và không bị cắt trên nhiều kích thước màn hình thiết bị.
Chuyển đổi sang Horologist ScalingLazyColumnState
Trong MainActivity.kt
, hãy tìm "TODO: Swap to ScalingLazyColumnState
" rồi thay thế nhận xét đó cũng như dòng bên dưới bằng mã sau đây. Lưu ý cách chúng ta chỉ định những thành phần nào là thành phần đầu tiên và thành phần cuối cùng để sử dụng các giá trị khoảng đệm phù hợp nhất nhằm tránh tình trạng nội dung bị cắt.
Bước 7
// TODO: Swap to ScalingLazyColumnState
val listState = rememberResponsiveColumnState(
contentPadding = ScalingLazyColumnDefaults.padding(
first = ItemType.SingleButton,
last = ItemType.Chip,
),
)
Tên gần giống hệt nhau. Cũng giống như LazyListState
xử lý trạng thái cho LazyColumn
, ScalingLazyColumnState
xử lý trạng thái cho ScalingLazyColumn
.
Chuyển đổi sang Horologist ScalingLazyColumn
Tiếp theo, chúng ta hoán đổi trong ScalingLazyColumn
.
Trong MainActivity.kt
, hãy tìm kiếm "TODO: Swap a ScalingLazyColumn
". Trước tiên, thay thế LazyColumn
bằng ScalingLazyColumn
của Horologist.
Sau đó, hãy xoá hoàn toàn contentPadding, verticalArrangement, modifier
và autocentering
– ScalingLazyColumn
của Horologist đã cung cấp các chế độ cài đặt mặc định đảm bảo rằng hiệu ứng hình ảnh mặc định sẽ tốt hơn vì hầu hết khung nhìn sẽ được lấp đầy bằng các mục trong danh sách. Trong nhiều trường hợp, chỉ cần tham số mặc định là đủ. Nếu có tiêu đề ở trên cùng thì bạn nên đặt tiêu đề đó vào ResponsiveListHeader
làm mục đầu tiên.
Bước 8
// TODO: Swap a ScalingLazyColumn (Wear's version of LazyColumn)
ScalingLazyColumn(
columnState = listState
Vậy là xong! Hãy cùng xem:
Bạn có thể thấy nội dung được chia tỷ lệ và độ trong suốt được điều chỉnh ở đầu và cuối màn hình khi bạn cuộn với rất ít thao tác để di chuyển!
Bạn có thể thực sự nhận thấy điều này với các thành phần kết hợp "meditation", khi bạn di chuyển lên và xuống.
Bây giờ, hãy chuyển sang chủ đề cuối cùng, Scaffold
của Wear OS.
8. Thêm Scaffold
Scaffold
cung cấp cấu trúc bố cục giúp bạn sắp xếp màn hình theo các mẫu chung, giống như cách sắp xếp trên thiết bị di động. Nhưng thay vì Thanh ứng dụng, FAB, Ngăn hoặc các phần tử cụ thể khác dành riêng cho thiết bị di động, Scaffold hỗ trợ 3 bố cục dành riêng cho Wear với các thành phần cấp cao: thời gian, chỉ báo cuộn/vị trí và chỉ báo trang.
Các thành phần đó sẽ có dạng như sau:
Chúng ta sẽ tìm hiểu chi tiết 3 thành phần đầu tiên, nhưng trước hết, hãy đặt scaffold vào vị trí.
Chúng ta sẽ dùng AppScaffold
và ScreenScaffold
của Horologist để thêm một TimeText
theo mặc định vào màn hình, cũng như để đảm bảo rằng TimeText đó tạo ảnh động chính xác khi di chuyển giữa các màn hình.
Ngoài ra, ScreenScaffold
thêm một PositionIndicator
cho nội dung có thể cuộn.
Thêm Scaffold
Hãy thêm ngay mã nguyên mẫu dành cho AppScaffold
và ScreenScaffold
.
Tìm "TODO (Start): Create a AppScaffold (Wear Version)
" rồi thêm mã ở bên dưới.
Bước 9
WearAppTheme {
// TODO (Start): Create a Horologist AppScaffold (Wear Version)
AppScaffold {
Tìm "TODO (Start): Create a ScreenScaffold (Wear Version)"
rồi thêm mã ở bên dưới.
// TODO (Start): Create a Horologist ScreenScaffold (Wear Version)
ScreenScaffold(
scrollState = listState,
){
Tiếp theo, hãy đảm bảo rằng bạn thêm dấu đóng ngoặc vào đúng vị trí.
Tìm "TODO (End): Create a ScreenScaffold (Wear Version)"
rồi thêm dấu đóng ngoặc vào đó:
Bước 10
// TODO (End): Create a ScreenScaffold (Wear Version)
}
Tìm "TODO (End): Create a AppScaffold (Wear Version)"
rồi thêm dấu đóng ngoặc vào đó:
Bước 10
// TODO (End): Create a AppScaffold (Wear Version)
}
Hãy chạy ứng dụng trước. Bạn sẽ thấy như sau:
Lưu ý rằng ứng dụng này bổ sung:
- Một
TimeText
sử dụng văn bản cong trong nền giúp nhà phát triển dễ dàng hiện thời gian mà không cần đặt thành phần kết hợp hoặc dùng tới lớp nào liên quan đến thời gian. Ngoài ra, theo Nguyên tắc của Material, bạn nên hiển thị thời gian ở đầu mọi màn hình trong ứng dụng và thời gian sẽ mờ dần khi cuộn. - Một
PositionIndicator
(còn gọi là Chỉ báo cuộn) là chỉ báo ở bên phải màn hình, cho biết vị trí chỉ báo hiện tại dựa trên loại đối tượng trạng thái mà bạn truyền vào. Trong trường hợp của chúng ta, đó sẽ làScalingLazyColumnState
.
Được rồi, hãy xem thành quả của chúng ta:
Hãy thử cuộn lên và xuống. Bạn sẽ chỉ thấy chỉ báo cuộn xuất hiện khi đang cuộn.
Tuyệt vời, bạn đã hoàn tất phần minh hoạ giao diện người dùng của hầu hết thành phần kết hợp Wear OS!
9. Xin chúc mừng
Xin chúc mừng! Bạn đã tìm hiểu các kiến thức cơ bản về việc sử dụng Compose on Wear OS!
Giờ đây, bạn có thể vận dụng tất cả kiến thức về Compose để tạo ra các ứng dụng Wear OS tuyệt đẹp!
Tiếp theo là gì?
Hãy tham khảo các lớp học lập trình khác về Wear OS:
Tài liệu đọc thêm
- Bài đăng Compose for Wear OS is now 1.0 (Compose cho Wear OS hiện đã có phiên bản 1.0) trên blog
- Mẫu đơn giản của Compose cho Wear OS trên GitHub
- Bài viết Dùng Wear OS để xây dựng ứng dụng cho thiết bị đeo tay (cung cấp thêm hướng dẫn)
Phản hồi
Chúng tôi rất mong được biết cảm nhận của bạn về trải nghiệm khi dùng Compose cho Wear OS và sản phẩm bạn có thể xây dựng! Hãy tham gia thảo luận trong kênh Kotlin Slack #compose-wear và cung cấp ý kiến phản hồi về công cụ theo dõi lỗi.
Chúc bạn lập trình vui vẻ!