資訊方塊不只會顯示資訊,還能提供互動功能。如要讓 textButton()
等元素回應輕觸動作,請使用 clickable()
產生點擊處理常式,並將其與版面配置元素建立關聯。
您可以透過兩種主要方式設定 Clickable
以觸發動作:
- 直接啟動活動:如果需要立即開啟活動,請使用
launchAction()
。 - 委派至資訊方塊服務:使用
loadAction()
觸發TileService
中的邏輯。這是更具彈性的做法,可讓您重新整理資訊方塊的內容、更新其狀態,或啟動更複雜的活動。
啟動匯出的活動
如果使用者輕觸後應立即啟動活動,請使用 launchAction()
。提供 ComponentName
來識別活動。活動必須匯出。使用這個方法,您可以透過動作傳遞 Intent
額外項目。不過,您無法設定自訂 Intent
標記。
以下範例說明如何建立 Clickable
,以便透過兩個額外項目 name
和 age
啟動 TileActivity
:
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), ), ) ), )
在啟動的活動中,從意圖額外項目擷取值:
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") // ... }
處理資訊方塊服務中的互動
如要提供更彈性的互動體驗,請使用 loadAction()
。當使用者輕觸以 loadAction
設定的元素時,系統會重新叫用您的 TileService.onTileRequest()
。這樣一來,您就能在服務中執行邏輯,以便更新圖塊、變更圖塊狀態,以及執行更複雜的工作。
重新整理資訊方塊內容
loadAction
最簡單的用途就是傳送重新整理信號。呼叫不含任何引數的 loadAction
。輕觸後,系統會呼叫 onTileRequest()
,讓服務傳回含有更新內容的新版面配置。
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
區分多個互動式元素
如果資訊方塊包含多個互動式元素,您可以使用 Clickable
修飾符將 ID 關聯:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
在 onTileRequest()
中,您可以使用 requestParams.currentState.lastClickableId
檢查此 ID,決定要執行哪些動作。
範例:使用深層連結啟動活動
此模式非常適合使用深層連結啟動活動。使用者輕觸重新載入圖塊,您的服務會檢查 ID,然後啟動新的活動。如要控制返回堆疊,請使用 TaskStackBuilder
為使用者提供更優質的導覽體驗。使用者輕觸元素後,系統會直接將他們導向深層連結畫面 (範例中的 message_detail/1
畫面)。由於使用了 .addNextIntentWithParentStack()
,因此父項活動也會新增至返回堆疊。也就是說,如果使用者滑動返回,他們會向上瀏覽應用程式的主畫面 (範例中的 MessageList
),而不是立即退出至資訊方塊。再次向後滑動即可返回資訊方塊。
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) // ... }
接著,在 TileActivity
中,將導覽設定與 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") } } }
使用 TaskStackBuilder
,為使用者提供更優質的導覽體驗。使用者輕觸元素後,系統會直接將他們導向深層連結畫面,在本例中就是 message_detail/1
畫面。由於使用了 .addNextIntentWithParentStack()
,因此父項活動也會新增至返回堆疊。也就是說,如果使用者滑動返回,他們會向上瀏覽應用程式的主畫面 (在本例中為 MessageList
),而不是立即退出並前往資訊方塊。再次向後滑動即可返回資訊方塊。
更新資訊方塊內的狀態
資訊方塊含有 StateBuilders.State
物件,可儲存鍵/值組合,並在重新載入時保留。當使用者與資訊方塊互動時,您可以使用 loadAction()
更新此狀態。
如要這麼做,請將 DynamicDataMap
傳遞至包含新狀態值的 loadAction()
。
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
當 onTileRequest()
受到這項動作觸發時,您可以從 requestParams.currentState.stateMap
讀取更新的資料。這對於直接修改資訊方塊資料的互動操作很有幫助,例如增加計數器或切換設定。
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")] } // ... }