Ansichten können nicht nur Informationen anzeigen, sondern auch interaktiv sein.
Wenn ein Element wie textButton()
auf Tippen reagieren soll, generieren Sie einen Klickhandler mit clickable()
und verknüpfen Sie ihn mit dem Layoutelement.
Sie haben zwei Möglichkeiten, eine Clickable
so zu konfigurieren, dass sie eine Aktion auslöst:
- Aktivität direkt starten: Verwenden Sie
launchAction()
, wenn Sie eine Aktivität sofort öffnen möchten. - Auf Ihren Ansichtsdienst verweisen: Verwenden Sie
loadAction()
, um Logik in IhremTileService
auszulösen. Dieser Ansatz ist flexibler, da Sie damit den Inhalt der Kachel aktualisieren, ihren Status aktualisieren oder eine komplexere Aktivität starten können.
Exportierte Aktivität starten
Wenn durch das Tippen eines Nutzers sofort eine Aktivität gestartet werden soll, verwenden Sie launchAction()
.
Geben Sie eine ComponentName
an, um die Aktivität zu identifizieren. Die Aktivität muss exportiert werden. Mit diesem Ansatz kannst du Intent
-Extras mit der Aktion übergeben.
Es ist jedoch nicht möglich, benutzerdefinierte Intent
-Flags festzulegen.
Das folgende Beispiel zeigt, wie Sie einen Clickable
erstellen, um TileActivity
mit zwei Extras, name
und age
, zu starten:
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), ), ) ), )
Rufen Sie in der gestarteten Aktivität die Werte aus den Intent-Extras ab:
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") // ... }
Interaktionen in Ihrem Ansichtsdienst verarbeiten
Für flexiblere Interaktionen verwenden Sie loadAction()
. Wenn ein Nutzer auf ein mit loadAction
konfiguriertes Element tippt, ruft das System Ihre TileService.onTileRequest()
noch einmal auf. So können Sie Logik in Ihrem Dienst ausführen, um die Kachel zu aktualisieren, ihren Status zu ändern und komplexere Aufgaben auszuführen.
Inhalt der Kachel aktualisieren
Die einfachste Verwendung von loadAction
ist das Signalisieren einer Aktualisierung. Rufen Sie loadAction
ohne Argumente auf. Wenn darauf getippt wird, ruft das System onTileRequest()
auf, sodass Ihr Dienst ein neues Layout mit aktualisierten Inhalten zurückgeben kann.
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
Zwischen mehreren interaktiven Elementen unterscheiden
Wenn Ihre Kachel mehrere interaktive Elemente enthält, können Sie dem Clickable
-Modifikator eine ID zuweisen:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
Innerhalb von onTileRequest()
können Sie diese ID mit requestParams.currentState.lastClickableId
prüfen, um zu entscheiden, welche Aktion ausgeführt werden soll.
Beispiel: Aktivität mit einem Deeplink starten
Dieses Muster eignet sich ideal, um eine Aktivität mit einem Deeplink zu starten. Durch das Tippen des Nutzers wird die Kachel neu geladen, Ihr Dienst prüft die ID und startet dann die neue Aktivität. Verwenden Sie zum Steuern des Backstacks ein TaskStackBuilder
, um die Navigation für den Nutzer zu vereinfachen. Wenn der Nutzer auf das Element tippt, wird er direkt zum Deeplink-Bildschirm weitergeleitet (message_detail/1
-Bildschirm im Beispiel). Da .addNextIntentWithParentStack()
verwendet wurde, wird auch die übergeordnete Aktivität dem Backstack hinzugefügt. Wenn der Nutzer also wischt, um zurückzugehen, gelangt er zum Hauptbildschirm der App (MessageList
im Beispiel), anstatt sofort zur Kachel zurückzukehren. Wenn Sie ein zweites Mal wischen, kehren Sie zur Kachel zurück.
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) // ... }
Konfigurieren Sie dann in TileActivity
die Navigation so, dass sie dem googleandroidsnippets://app/message_detail/{id}
-Muster entspricht.
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") } } }
Verwende TaskStackBuilder
, um die Navigation für Nutzer zu verbessern.
Wenn der Nutzer auf das Element tippt, wird er direkt zum Deeplink-Bildschirm weitergeleitet. In diesem Beispiel ist das der Bildschirm message_detail/1
. Da .addNextIntentWithParentStack()
verwendet wurde, wird die übergeordnete Aktivität auch dem Backstack hinzugefügt. Wenn der Nutzer also wischt, gelangt er zum Hauptbildschirm der App (MessageList
im Beispiel), anstatt sofort zur Kachel zurückzukehren. Wenn Sie ein zweites Mal wischen, kehren Sie zur Kachel zurück.
Status in der Kachel aktualisieren
Ihre Kachel enthält ein StateBuilders.State
-Objekt, in dem Schlüssel/Wert-Paare gespeichert werden, die nach dem Aktualisieren erhalten bleiben. Sie können diesen Status mit loadAction()
aktualisieren, wenn ein Nutzer mit der Kachel interagiert.
Übergeben Sie dazu loadAction()
einen DynamicDataMap
mit den neuen Statuswerten.
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
Wenn onTileRequest()
durch diese Aktion ausgelöst wird, können Sie die aktualisierten Daten aus requestParams.currentState.stateMap
lesen. Das ist nützlich für Interaktionen, die Daten auf der Kachel direkt ändern, z. B. das Erhöhen eines Zählers oder das Umschalten einer Einstellung.
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")] } // ... }