Interagire con i riquadri

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:

  1. Avvia direttamente un'attività: utilizza launchAction() nei casi in cui devi aprire immediatamente un'attività.
  2. Delega al servizio delle schede: utilizza loadAction() per attivare la logica all'interno di TileService. 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:

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.

Poi, in TileActivity, configura la navigazione in modo che corrisponda al pattern googleandroidsnippets://app/message_detail/{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")]
    }

    // ...
}