Lớp học lập trình về Compose cho Wear OS

1. Giới thiệu

11ba5a682f1ffca3.png

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 các thiết bị đeo.

Với tính năng hỗ trợ tích hợp sẵn dành cho Material You, Compose cho Wear OS sẽ đơn giản hoá và tăng tốc độ 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 và 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:

31cb08c0fa035400.gif

Điều kiện tiên quyết

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 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 1 trong 2 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ụ.

400c194c8948c952.png

Mở dự án trong Android Studio

  1. 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 61d0a4432ef6d396.png Open an Existing Project (Mở một dự án hiện có)
  2. Chọn thư mục [Download Location]
  3. 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 startfinished trên một trình mô phỏng hoặc thiết bị Wear OS thực.
  4. 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.

c82b07a089099c4f.png

Tìm hiểu mã khởi đầ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ệp Color, TypeTheme 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ư ScaffoldScalingLazyList) 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 trên cùng (đánh dấu bằng màu đỏ trong hình dưới đây).

d64d9c262a79271.png

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.*)

androidx.wear.compose:compose-material

thay cho

androidx.compose.material:material

androidx.wear.compose:compose-navigation

thay cho

androidx.navigation:navigation-compose

androidx.wear.compose:compose-foundation

bổ sung cho

androidx.compose.foundation:foundation

androidx.wear.compose:compose-ui-tooling

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:

// TODO: Review Dependencies
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 đặt 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, TextCard) 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:

c9b981101ae653db.png

Có thể bạn đã từng viết mã này rồi (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:

b33172e992d1ea3e.png

Hàm có khả năng 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 Text (Văn bản) trong màu material chính.

Chuỗi này được lấy từ tệp res/values/strings.xml. Trên thực tế, nếu nhìn trong thư mục res/values, bạn sẽ thấy 2 tệp tài nguyên strings.xml.

Đế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à AppCardTitleCard.

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:

1fc761252ac5b466.png

Tại thời điểm này, có lẽ bạn nhận ra rằng đố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 ChipToggleChip.

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.

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):

d97151e85e9a1e03.png

Được rồi, hãy xem một 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:

ea1a76abd54877b.png

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ạ:

198ee8e8fa799f08.gif

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:

a5a83ab2e5d5230f.gif

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 những kích thước màn hình thiết bị khác nhau.

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, modifierautocenteringScalingLazyColumn 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:

5c25062081307944.png

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ợ 4 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:

TimeText

PositionIndicator

PageIndicator

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 AppScaffoldScreenScaffold của Horologist để thêm TimeText vào màn hình theo mặc định và đảm bảo 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 AppScaffoldScreenScaffold.

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 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 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:

ff554156bbe03abb.png

Lưu ý rằng ứng dụng này bổ sung:

  • TimeText sử dụng văn bản cong 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 đến 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.
  • 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 ngay thành quả dưới đây:

cfcbd3003744a6d.png

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

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ẻ!