Eseguire la migrazione dell'interfaccia utente ai layout adattabili

Le app Android devono supportare un ecosistema di fattori di forma dei dispositivi in continua espansione. L'interfaccia utente di un'app deve essere reattiva per adattarsi a schermi di varie dimensioni, nonché a orientamenti e stati del dispositivo diversi.

L'interfaccia utente reattiva è incentrata sui principi di flessibilità e continuità.

La flessibilità si riferisce ai layout che utilizzano in modo ottimale lo spazio disponibile e si adattano in caso di variazioni dello spazio disponibile. Gli aggiustamenti possono assumere molte forme: semplicemente aumentare le dimensioni di una singola vista, riposizionare le viste in modo che si trovino in posizioni più accessibili, mostrare o nascondere altre viste o una combinazione di queste.

Per continuità si intende un'esperienza utente fluida durante la transizione da una dimensione di finestra a un'altra. Qualunque sia l'esperienza in cui l'utente è coinvolto dovrebbe continuare senza interruzioni. Poiché una variazione delle dimensioni potrebbe essere accompagnata dall'eliminazione e dalla ricreazione dell'intera gerarchia delle visualizzazioni, è importante che l'utente non perda la posizione in cui si trovano o i propri dati.

Cose da evitare

Evitare di utilizzare valori fisici e hardware per prendere decisioni sul layout. La tentazione di prendere decisioni basate su un valore fisso potrebbe essere forte, ma in molte situazioni questi valori non sono utili per determinare lo spazio con cui può funzionare l'interfaccia utente.

Sui tablet, un'app potrebbe essere eseguita in modalità multi-finestra, il che significa che l'app condivide lo schermo con un'altra app. Su ChromeOS, un'app potrebbe essere in una finestra ridimensionabile. Possono anche esserci più schermi fisici, ad esempio un dispositivo pieghevole o un dispositivo con più display. In tutti questi casi, le dimensioni dello schermo fisico non sono pertinenti ai fini della scelta della modalità di visualizzazione dei contenuti.

Più dispositivi che mostrano finestre di app di dimensioni diverse.
Figura 1. Le dimensioni della finestra possono variare rispetto alle dimensioni del display o del dispositivo fisico.

Per lo stesso motivo, evita di bloccare l'app su un orientamento o proporzioni specifico. Anche se il dispositivo stesso può avere un orientamento particolare, l'app potrebbe avere un orientamento diverso esclusivamente in base alle dimensioni della finestra. Ad esempio, se usi un tablet in modalità orizzontale in modalità multi-finestra, un'app può essere in verticale perché è più alta che larga.

Inoltre, evita di provare a stabilire se il dispositivo è un telefono o un tablet. Quello che in particolare viene definito tablet è piuttosto soggettivo: è basato sulle dimensioni, sulle proporzioni o su una combinazione di dimensioni e proporzioni ? Man mano che emergono nuovi fattori di forma, queste ipotesi possono cambiare e la distinzione perde importanza.

Anziché provare una delle strategie precedenti, utilizza i punti di interruzione e le classi di dimensioni delle finestre.

Punti di interruzione e classi di dimensioni delle finestre

La parte effettiva dello schermo assegnata alla tua app è la finestra dell'app. Potrebbe occupare tutto lo schermo o parte dello schermo, pertanto ti consigliamo di usare le dimensioni della finestra per prendere decisioni importanti in merito al layout della tua app.

Quando progetti per più fattori di forma, trova i valori soglia in cui queste decisioni di alto livello si diramano in direzioni diverse. A questo scopo, la griglia di layout adattabile di Material Design fornisce punti di interruzione per larghezza e altezza, che ti consentono di mappare le dimensioni non elaborate in gruppi standardizzati discreti, denominati classi di dimensioni delle finestre. Data l'ubiquità dello scorrimento verticale, la maggior parte delle app si preoccupa principalmente delle classi di larghezza per le dimensioni, pertanto la maggior parte delle app può essere ottimizzata per schermi di tutte le dimensioni gestendo solo alcuni punti di interruzione. Per ulteriori informazioni sulle classi di dimensioni delle finestre, consulta Supporto di schermi di dimensioni diverse.

Elementi UI permanenti

Le linee guida per il layout di Material Design definiscono le regioni per barre delle app, navigazione e contenuti. In genere, i primi due sono elementi UI permanenti nella radice (o molto vicina) alla radice della gerarchia delle visualizzazioni. Tieni presente che "persistente" non significa necessariamente che la visualizzazione sia sempre visibile, ma piuttosto che rimanga attiva mentre altre visualizzazioni di contenuti potrebbero spostarsi o cambiare. Ad esempio, un elemento di navigazione potrebbe trovarsi in un cassetto scorrevole senza schermo, ma il riquadro a scomparsa è sempre lì.

Gli elementi permanenti possono essere adattabili e di solito occupano tutta la larghezza o l'intera altezza della finestra, perciò è preferibile utilizzare le classi di dimensioni per decidere dove posizionarli. in modo da delineare lo spazio riservato ai contenuti. Nel seguente snippet, l'attività utilizza una barra inferiore per gli schermi compatti e una barra dell'app in alto per gli schermi più grandi. I layout idonei usano punti di interruzione larghezza come descritto in precedenza.

<!-- res/layout/main_activity.xml -->

<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <!-- content view(s) -->

    <com.google.android.material.bottomappbar.BottomAppBar
        android:layout_width="wrap_content"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent"
        ... />
</androidx.constraintlayout.widget.ConstraintLayout>


<!-- res/layout-w600dp/main_activity.xml -->
<androidx.constraintlayout.widget.ConstraintLayout
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <com.google.android.material.appbar.AppBarLayout
        android:layout_width="0dp"
        android:layout_height="wrap_content"
        app:layout_constraintTop_toTopOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        ... />

    <!-- content view(s) -->
</androidx.constraintlayout.widget.ConstraintLayout>

Contenuti

Dopo aver posizionato gli elementi permanenti dell'interfaccia utente, utilizza lo spazio rimanente per i contenuti, ad esempio utilizzando NavHostFragment con il grafico di navigazione dell'app. Per ulteriori considerazioni, consulta Navigazione per le UI adattabili.

Assicurati che tutti i dati siano disponibili per dimensioni diverse

La maggior parte dei framework delle app oggi utilizza un modello di dati separato dai componenti Android che contribuiscono all'interfaccia utente (attività, frammenti e visualizzazioni). Con Jetpack, questo ruolo è in genere completato da ViewModels, che hanno l'ulteriore vantaggio di essere sopravvissuti alle modifiche alla configurazione (per ulteriori informazioni, consulta la pagina ViewModel Overview).

Quando implementi un layout che si adatta a dimensioni diverse, potresti avere la tentazione di utilizzare un modello di dati diverso in base alle dimensioni attuali. Tuttavia, questo viola il principio del flusso di dati unidirezionale. I dati dovrebbero scorrere verso il basso in Visualizzazioni e gli eventi come le interazioni degli utenti dovrebbero essere verso l'alto. La creazione di una dipendenza nell'altra direzione, in cui il modello dei dati dipende dalla configurazione del livello UI, complica drasticamente il problema. Quando l'app cambia dimensioni, devi tenere conto della conversione da un modello di dati a un altro.

Lascia invece che il tuo modello dati rientri nella classe di dimensioni più grande e poi puoi mostrare, nascondere o riposizionare in modo selettivo i contenuti nell'interfaccia utente per adattarli alla classe dimensione corrente. Di seguito sono riportate alcune strategie che puoi utilizzare per decidere come deve comportarsi il layout nel passaggio da una classe di dimensioni all'altra.

Espandi i contenuti

Layout canonici: feed

L'ampliamento dello spazio può rappresentare un'opportunità per ingrandirle e riformattare i contenuti in modo da renderli più accessibili.

Ingrandisci le raccolte. Molte app mostrano una raccolta di elementi in un contenitore a scorrimento, come RecyclerView o ScrollView. Se consenti a un contenitore di ingrandire automaticamente le dimensioni, possono essere visualizzati più contenuti. Tuttavia, verifica che i contenuti del contenitore non risultino eccessivamente allungati o distorti. Ad esempio, con un valore RecyclerView, puoi utilizzare uno strumento di gestione del layout diverso, come GridLayoutManager, StaggeredGridLayoutManager o FlexboxLayout quando la larghezza non è compatta.

Un dispositivo piegato e aperto che mostra come i diversi gestori del layout dispongono l&#39;app in modo diverso in base alla classe delle dimensioni della larghezza.
Figura 2. Gestori del layout diversi per classi di dimensioni delle finestre diverse.

I singoli elementi possono anche utilizzare dimensioni o forme diverse per visualizzare più contenuti e distinguere più facilmente i confini degli elementi.

Evidenziare un elemento hero. Se il layout ha un punto focale particolare, ad esempio un'immagine o un video, espandilo quando la finestra dell'app si allunga per mantenere l'attenzione dell'utente. Altri elementi di supporto possono essere riorganizzati intorno o sotto la visualizzazione hero.

Esistono molti modi per creare un layout di questo tipo, ma ConstraintLayout è particolarmente adatto a questo scopo perché offre molti modi per limitare le dimensioni di una vista secondaria, tra cui la percentuale o l'applicazione di proporzioni e per posizionare gli elementi secondari rispetto a se stesso o ad altri elementi secondari. Scopri di più su tutte queste funzionalità nell'articolo Creare un'interfaccia utente adattabile con ConstraintLayout.

Mostra i contenuti comprimibili per impostazione predefinita. Quando c'è spazio disponibile, mostra contenuti che altrimenti sarebbero accessibili solo tramite interazioni aggiuntive dell'utente, come tocco, scorrimento o gesti. Ad esempio, i contenuti visualizzati in un'interfaccia a schede quando sono compatti possono essere riorganizzati in colonne o in un elenco quando c'è più spazio disponibile.

Espandi i margini. Se lo spazio è così grande che non riesci a trovare una soluzione accattivante anche dopo aver utilizzato tutti i tuoi contenuti, espandi i margini del layout in modo che i contenuti rimangano centrati e le singole visualizzazioni abbiano dimensioni e spazi naturali tra di loro.

In alternativa, un componente a schermo intero può trasformarsi in UI di dialogo mobile. Questa opzione è particolarmente adatta quando il componente richiede uno stato attivo esclusivo per svolgere un'attività immediata dell'utente, come scrivere un'email o creare un evento di calendario.

Un telefono standard su cui è mostrata una finestra di dialogo a schermo intero e un telefono pieghevole aperto che mostra la stessa finestra di dialogo di una finestra mobile.
Figura 3. Finestra di dialogo a schermo intero trasformata in una finestra di dialogo standard di larghezza media e espansa.

Aggiungi contenuti

Layout canonici: riquadro di supporto, visualizzazione dettaglio elenco

Utilizza un riquadro di supporto. Un riquadro di supporto presenta contenuti aggiuntivi o azioni contestuali correlate ai contenuti principali, come i commenti in un documento o gli elementi di una playlist. In genere, utilizzano il terzo inferiore dello schermo per l'altezza espansa o il terzo finale per la larghezza espansa.

Una considerazione importante è la posizione in cui posizionare questi contenuti se lo spazio non è sufficiente per mostrare il riquadro. Ecco alcune alternative da provare:

  • Riquadro a scomparsa laterale sul bordo finale utilizzando DrawerLayout
  • Riquadro a scomparsa inferiore utilizzando BottomSheetBehavior
  • Menu o finestra popup accessibile toccando l'icona di un menu
Figura 4. Metodi alternativi per presentare contenuti aggiuntivi in un riquadro di supporto.

Crea un layout a due riquadri. Gli schermi di grandi dimensioni potrebbero mostrare una combinazione di funzionalità che in genere vengono visualizzate separatamente su schermi più piccoli. Uno schema di interazione comune in molte app è mostrare un elenco di elementi, come contatti o risultati di ricerca, e passare ai dettagli di un elemento quando viene selezionato. Anziché ingrandire l'elenco per gli schermi più grandi, utilizza la visualizzazione elenco-dettaglio per mostrare entrambe le funzionalità affiancate in un layout a due riquadri. A differenza di un riquadro di supporto, il riquadro dei dettagli di una visualizzazione dei dettagli elenco è un elemento autonomo che può essere mostrato in modo indipendente su schermi più piccoli.

Utilizza il widget dedicato SlidingPaneLayout per implementare una visualizzazione dei dettagli elenco. Questo widget calcola automaticamente se lo spazio è sufficiente per visualizzare entrambi i riquadri in base al valore layout_width specificato per i due riquadri e l'eventuale spazio residuo può essere distribuito utilizzando layout_weight. Se lo spazio non è sufficiente, ogni riquadro utilizza l'intera larghezza del layout e il riquadro dei dettagli viene spostato fuori dallo schermo o in cima al riquadro dell'elenco.

SlidingPaneLayout che mostra entrambi i riquadri con un layout con dettagli elenco su un dispositivo con un ampio display.
Figura 5. SlidingPaneLayout che mostra due riquadri in larghezza espansa e un riquadro a larghezza compatta.

La creazione di un layout a due riquadri contiene ulteriori dettagli sull'utilizzo di SlidingPaneLayout. Tieni inoltre presente che questo pattern può influire sulla struttura del grafico di navigazione (vedi Navigazione per UI adattabili).

Risorse aggiuntive