I riquadri possono fare di più che visualizzare informazioni: possono anche essere interattivi.
Per fare in modo che un elemento come textButton()
risponda ai tocchi, genera un gestore dei clic utilizzando clickable()
e associalo all'elemento di layout.
Puoi configurare un Clickable
per attivare un'azione in due modi principali:
- Avvia direttamente un'attività: utilizza
launchAction()
nei casi in cui devi aprire immediatamente un'attività. - Delega al servizio delle schede: utilizza
loadAction()
per attivare la logica all'interno diTileService
. Si tratta di un approccio più flessibile che ti consente di aggiornare i contenuti del riquadro, aggiornarne lo stato o avviare un'attività più complessa.
Avviare un'attività esportata
Se un tocco dell'utente deve avviare immediatamente un'attività, utilizza launchAction()
.
Fornisci un ComponentName
per identificare l'attività. L'attività deve essere
esportata. Con questo approccio, puoi passare Intent
extra con l'azione.
Tuttavia, non è possibile impostare flag Intent
personalizzati.
L'esempio seguente mostra come creare un Clickable
per lanciare TileActivity
con due extra, name
e 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), ), ) ), )
All'interno dell'attività lanciata, recupera i valori dagli extra dell'intent:
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") // ... }
Gestire le interazioni nel servizio di riquadri
Per interazioni più flessibili, utilizza loadAction()
. Quando un utente tocca un elemento configurato con loadAction
, il sistema richiama nuovamente il tuo TileService.onTileRequest()
. In questo modo puoi eseguire la logica nel servizio per
aggiornare il riquadro, modificarne lo stato ed eseguire attività più complesse.
Aggiornare i contenuti della scheda
L'uso più semplice di loadAction
è segnalare un aggiornamento. Chiama loadAction
senza argomenti. Quando viene toccato, il sistema chiama onTileRequest()
, consentendo al tuo servizio di restituire un nuovo layout con contenuti aggiornati.
textButton( onClick = clickable(loadAction()), labelContent = { text("Refresh".layoutString) }, )
Distinguere tra più elementi interattivi
Se il riquadro contiene più elementi interattivi, puoi associare un ID con il modificatore Clickable
:
textButton( labelContent = { text("Deep Link me!".layoutString, typography = BODY_LARGE) }, onClick = clickable(id = "foo", action = loadAction()), )
In onTileRequest()
, puoi controllare questo ID utilizzando
requestParams.currentState.lastClickableId
per decidere quale azione eseguire.
Esempio: avvio di un'attività con un link diretto
Questo pattern è ideale per avviare un'attività con un link diretto. Il tap dell'utente ricarica il riquadro, il servizio ispeziona l'ID e avvia la nuova attività. Per controllare la pila di navigazione a ritroso, utilizza un TaskStackBuilder
per offrire all'utente un'esperienza di navigazione migliore. Quando l'utente tocca l'elemento, viene indirizzato direttamente alla schermata del link diretto (la schermata message_detail/1
dell'esempio). Poiché è stato utilizzato .addNextIntentWithParentStack()
, anche l'attività principale viene aggiunta alla pila di ritorno. Ciò significa che se l'utente sblocca
indietro, verrà visualizzato il riquadro della schermata principale dell'app (MessageList
nell'
esempio) anziché uscire immediatamente al riquadro. Se scorri di nuovo verso il retro,
viene visualizzato nuovamente il riquadro.
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) // ... }
Poi, in TileActivity
, configura la navigazione in modo che corrisponda al pattern 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") } } }
Utilizza TaskStackBuilder
per offrire all'utente un'esperienza di navigazione migliore.
Quando l'utente tocca l'elemento, viene indirizzato direttamente alla schermata con link diretto, in questo esempio la schermata message_detail/1
. Poiché è stato utilizzato
.addNextIntentWithParentStack()
, anche l'attività principale viene
aggiunta alla pila precedente. Ciò significa che se l'utente scorre verso il retro, verrà visualizzato
la schermata principale dell'app (MessageList
nell'esempio) anziché uscire immediatamente
al riquadro. Se scorri di nuovo verso il retro, tornerai al riquadro.
Aggiorna lo stato all'interno del riquadro
Il riquadro contiene un oggetto StateBuilders.State
che memorizza coppie chiave-valore
e rimane invariato dopo i ricaricamenti. Puoi utilizzare loadAction()
per aggiornare questo stato quando un utente interagisce con il riquadro.
A questo scopo, passa un DynamicDataMap
a loadAction()
contenente i nuovi valori dello stato.
textButton( labelContent = { text("loadAction()".layoutString, typography = BODY_LARGE) }, onClick = clickable( action = loadAction( dynamicDataMapOf( stringAppDataKey("name") mapTo "Javier", intAppDataKey("age") mapTo 37, ) ) ), )
Quando onTileRequest()
viene attivato da questa azione, puoi leggere i dati aggiornati da requestParams.currentState.stateMap
. Questo è utile per le interazioni
che modificano direttamente i dati nel riquadro, ad esempio l'incremento di un contatore o l'attivazione/disattivazione di un'impostazione.
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")] } // ... }