Thẻ thông tin không chỉ hiển thị thông tin mà còn có thể tương tác.
Để tạo một phần tử như textButton()
phản hồi các thao tác nhấn, hãy tạo một trình xử lý lượt nhấp bằng clickable()
và liên kết trình xử lý đó với phần tử bố cục.
Bạn có thể định cấu hình Clickable
để kích hoạt một hành động theo hai cách chính:
- Khởi chạy hoạt động trực tiếp: Sử dụng
launchAction()
trong trường hợp bạn cần mở một hoạt động ngay lập tức. - Uỷ quyền cho dịch vụ thẻ thông tin: Sử dụng
loadAction()
để kích hoạt logic trongTileService
. Đây là một phương pháp linh hoạt hơn cho phép bạn làm mới nội dung của thẻ thông tin, cập nhật trạng thái của thẻ thông tin hoặc khởi chạy một hoạt động phức tạp hơn.
Chạy một hoạt động đã xuất
Nếu một thao tác nhấn của người dùng sẽ ngay lập tức khởi chạy một hoạt động, hãy sử dụng launchAction()
.
Cung cấp ComponentName
để xác định hoạt động. Bạn phải xuất hoạt động. Với phương pháp này, bạn có thể truyền các phần bổ sung Intent
bằng thao tác.
Tuy nhiên, bạn không thể đặt cờ Intent
tuỳ chỉnh.
Ví dụ sau đây cho biết cách tạo Clickable
để chạy TileActivity
với hai phần bổ sung là name
và age
:
textButton( labelContent = { text("launchAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = launchAction( ComponentName( "com.example.wear", "com.example.wear.snippets.m3.tile.TileActivity", ), mapOf( "name" to ActionBuilders.stringExtra("Bartholomew"), "age" to ActionBuilders.intExtra(21), ), ) ), )
Bên trong hoạt động đã chạy, hãy truy xuất các giá trị từ các phần bổ sung của ý định:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // When this activity is launched from the tile InteractionLaunchAction, // "name" will be "Bartholomew" and "age" will be 21 val name = intent.getStringExtra("name") val age = intent.getStringExtra("age") // ... }
Xử lý các lượt tương tác trong dịch vụ thẻ thông tin
Để tương tác linh hoạt hơn, hãy sử dụng loadAction()
. Khi người dùng nhấn vào một phần tử được định cấu hình bằng loadAction
, hệ thống sẽ gọi lại TileService.onTileRequest()
. Điều này cho phép bạn chạy logic trong dịch vụ của mình để cập nhật thẻ thông tin, thay đổi trạng thái của thẻ thông tin và thực hiện các tác vụ phức tạp hơn.
Làm mới nội dung của thẻ thông tin
Cách sử dụng loadAction
đơn giản nhất là báo hiệu làm mới. Gọi loadAction
mà không có đối số. Khi được nhấn vào, hệ thống sẽ gọi onTileRequest()
, cho phép dịch vụ của bạn trả về một bố cục mới có nội dung đã cập nhật.
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
Phân biệt giữa nhiều thành phần tương tác
Nếu thẻ thông tin của bạn chứa nhiều phần tử tương tác, bạn có thể liên kết một mã nhận dạng với đối tượng sửa đổi Clickable
:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
Bên trong onTileRequest()
, bạn có thể kiểm tra mã nhận dạng này bằng cách sử dụng requestParams.currentState.lastClickableId
để quyết định hành động cần thực hiện.
Ví dụ: Chạy một hoạt động bằng đường liên kết sâu
Mẫu này rất phù hợp để khởi chạy một hoạt động bằng đường liên kết sâu. Thao tác nhấn của người dùng sẽ tải lại thẻ thông tin, dịch vụ của bạn sẽ kiểm tra mã nhận dạng, sau đó khởi chạy hoạt động mới. Để kiểm soát ngăn xếp lui, hãy sử dụng TaskStackBuilder
để mang lại trải nghiệm điều hướng tốt hơn cho người dùng. Khi người dùng nhấn vào phần tử này, họ sẽ được chuyển thẳng đến màn hình được liên kết sâu (màn hình message_detail/1
trong ví dụ). Vì đã sử dụng .addNextIntentWithParentStack()
, nên hoạt động mẹ cũng được thêm vào ngăn xếp lui. Điều này có nghĩa là nếu người dùng vuốt ngược, họ sẽ chuyển đến màn hình chính của ứng dụng (MessageList
trong ví dụ) thay vì thoát ngay đến thẻ thông tin. Thao tác vuốt ngược lần thứ hai sẽ đưa các thẻ thông tin đó trở lại thẻ thông tin.
override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile?> { val lastClickableId = requestParams.currentState.lastClickableId if (lastClickableId == "foo") { TaskStackBuilder.create(this) .addNextIntentWithParentStack( Intent( Intent.ACTION_VIEW, "googleandroidsnippets://app/message_detail/1".toUri(), this, TileActivity::class.java, ) ) .startActivities() } // ... User didn't tap a button (either first load or tapped somewhere else) // ... }
Sau đó, trong TileActivity
, hãy định cấu hình điều hướng để khớp với mẫu googleandroidsnippets://app/message_detail/{id}
.
AppScaffold { val navController = rememberSwipeDismissableNavController() SwipeDismissableNavHost( navController = navController, startDestination = "message_list", ) { // ... composable( route = "message_detail/{id}", deepLinks = listOf( navDeepLink { uriPattern = "googleandroidsnippets://app/message_detail/{id}" } ), ) { val id = it.arguments?.getString("id") ?: "0" MessageDetails(details = "message $id") } } }
Sử dụng TaskStackBuilder
để mang lại trải nghiệm điều hướng tốt hơn cho người dùng.
Khi người dùng nhấn vào phần tử này, họ sẽ được chuyển thẳng đến màn hình được liên kết sâu – trong ví dụ này, đó là màn hình message_detail/1
. Vì đã sử dụng .addNextIntentWithParentStack()
, nên hoạt động mẹ cũng được thêm vào ngăn xếp lui. Điều này có nghĩa là nếu người dùng vuốt ngược, họ sẽ chuyển đến màn hình chính của ứng dụng (MessageList
trong ví dụ) thay vì thoát ngay đến thẻ thông tin. Khi vuốt ngược lại lần thứ hai, các thẻ thông tin sẽ quay lại thẻ thông tin.
Cập nhật trạng thái trong thẻ thông tin
Thẻ thông tin của bạn có một đối tượng StateBuilders.State
lưu trữ các cặp khoá-giá trị và tồn tại trong các lần tải lại. Bạn có thể sử dụng loadAction()
để cập nhật trạng thái này khi người dùng tương tác với thẻ thông tin.
Để thực hiện việc này, hãy truyền DynamicDataMap
vào loadAction()
chứa các giá trị trạng thái mới.
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
Khi thao tác này kích hoạt onTileRequest()
, bạn có thể đọc dữ liệu đã cập nhật từ requestParams.currentState.stateMap
. Điều này rất hữu ích cho các hoạt động tương tác trực tiếp sửa đổi dữ liệu trên thẻ thông tin, chẳng hạn như tăng bộ đếm hoặc bật/tắt chế độ cài đặt.
override fun onTileRequest( requestParams: RequestBuilders.TileRequest ): ListenableFuture<Tile> { // When triggered by loadAction(), "name" will be "Javier", and "age" will // be 37. with(requestParams.currentState.stateMap) { val name = this[stringAppDataKey("name")] val age = this[intAppDataKey("age")] } // ... }