Target di messa a fuoco del gruppo

Puoi raggruppare più target di selezione utilizzando il modificatore focusGroup. Il raggruppamento ti consente di gestire le gerarchie di stato attivo, isolare le regioni logiche della UI (come barre degli strumenti, azioni delle finestre di dialogo o elenchi di schede) e intercettare quando lo stato attivo entra o esce da una regione.

Concetti relativi ai gruppi di selezione: entrata, uscita e attraversamento predefinito

Un gruppo di selezione stabilisce un confine di navigazione coeso attorno ai suoi target di selezione secondari. Per capire come lo stato attivo si sposta oltre questo confine, è necessario comprendere due concetti chiave:

  • Enter: l'evento che si verifica quando lo stato attivo passa da un elemento esterno al gruppo di elementi attivabili a un elemento interno al gruppo.
  • Uscita: l'evento che si verifica quando lo stato attivo lascia l'ultimo elemento interno del gruppo e passa a un target di stato attivo esterno.
Diagramma che mostra le transizioni di entrata e uscita attraverso un confine del gruppo di selezione.
Figura 1. Focus group con eventi di entrata e uscita.

Comportamento di attraversamento dello stato attivo predefinito

Per impostazione predefinita, quando un focus group riceve lo stato attivo dall'esterno:

  1. Accesso al gruppo: Compose seleziona automaticamente un target secondario interno per lo stato attivo. Per la navigazione unidimensionale (Tab), seleziona il primo elemento secondario nell'ordine di visualizzazione. Per la navigazione bidimensionale (tasto Freccia o D-pad), seleziona l'elemento secondario geometricamente più vicino alla direzione in entrata.
  2. Navigazione all'interno del gruppo: la pressione ripetuta dei tasti di navigazione sposta lo stato attivo tra i target di selezione di pari livello racchiusi nel gruppo.
  3. Uscita dal gruppo: una volta che l'utente ha superato l'ultimo target di attivazione all'interno del gruppo, la pressione del tasto successivo comporta l'uscita dal gruppo e lo spostamento dello stato attivo sul target di attivazione adiacente all'esterno del gruppo.

Personalizza il reindirizzamento della voce di selezione

In molti design della UI, il target di immissione predefinito (ad esempio il primo elemento secondario nell'ordine di visualizzazione) non è la scelta più logica o conveniente per l'utente.

Intenzione e casi d'uso

Considera una finestra di dialogo di conferma con un pulsante "Annulla" a sinistra e un pulsante principale "Conferma" a destra. Quando l'utente passa alla barra dei pulsanti da un campo del modulo:

  • Comportamento predefinito: lo stato attivo si posiziona su "Annulla" perché è il primo pulsante nell'ordine di visualizzazione.
  • Comportamento previsto: poiché "Conferma" è l'azione principale consigliata, potresti voler impostare lo stato attivo direttamente su "Conferma" quando entri nel gruppo di pulsanti dall'ordine di attivazione precedente, consentendo comunque all'utente di premere Sinistra per selezionare "Annulla", se necessario.
Impostazione predefinita dello stato attivo in un gruppo di pulsanti.
Figura 2. Pulsanti Annulla e Conferma con target di attivazione dello stato attivo predefinito.

Altri casi d'uso comuni includono:

  • Spostamento dello stato attivo direttamente sulla scheda attualmente selezionata quando si accede a un TabRow.
  • Spostamento dello stato attivo direttamente sul controllo "Riproduci / Pausa" quando si accede a una barra di riproduzione multimediale.

Implementazione con onEnter e FocusRequester

Per reindirizzare lo stato attivo quando si entra in un gruppo di elementi attivabili:

  1. Applica il modificatore focusGroup al container principale che racchiude i target di attivazione correlati.
  2. Applica il modificatore focusProperties al container e configura il callback onEnter.
  3. Nel callback onEnter (con ambito FocusEnterExitScope), chiama requestFocus() su un FocusRequester associato al figlio predefinito preferito utilizzando focusRequester.

val defaultChildRequester = remember { FocusRequester() }

Row(
    modifier = Modifier
        .focusGroup()
        .focusProperties {
            // Intercept entry into this group and redirect focus to the primary action
            onEnter = {
                defaultChildRequester.requestFocus()
            }
        }
) {
    Button(onClick = { /* Cancel action */ }) {
        Text("Cancel")
    }
    Button(
        onClick = { /* Confirm action */ },
        modifier = Modifier.focusRequester(defaultChildRequester)
    ) {
        Text("Confirm (Default)")
    }
}

All'interno di onEnter e onExit, puoi anche chiamare cancelFocusChange() per bloccare completamente le transizioni dello stato attivo oltre il confine o ispezionare requestedFocusDirection per personalizzare il routing in base al fatto che l'utente abbia navigato utilizzando Tab, Giù o Sinistra.

I contenitori scorrevoli sono gruppi di selezione per impostazione predefinita

In Jetpack Compose, i contenitori scorrevoli come LazyRow, LazyColumn e LazyVerticalGrid fungono automaticamente da gruppi di selezione. Non è necessario applicare esplicitamente il modificatore focusGroup per impostare i callback onEnter o onExit.