Esegui la migrazione dell'interfaccia utente ai layout adattabili

Le app per Android devono supportare un ecosistema in continua espansione di fattori di forma dei dispositivi. L'interfaccia utente di un'app deve essere adattabile a una vasta gamma di dimensioni dello schermo, nonché a diversi orientamenti e stati del dispositivo.

L'interfaccia utente adattabile si basa sui principi di flessibilità e continuità.

Per flessibilità si intendono i layout che sfruttano al meglio lo spazio disponibile e si adattano quando questo cambia. Gli aggiustamenti possono assumere molte forme: aumentare semplicemente le dimensioni di una singola visualizzazione, riorganizzare le visualizzazioni in modo che si trovino in posizioni più accessibili, mostrare o nascondere visualizzazioni aggiuntive o una combinazione di queste.

Con continuità si intende un'esperienza utente senza interruzioni durante il passaggio da una dimensione della finestra all'altra. Qualsiasi esperienza in cui l'utente è impegnato deve continuare senza interruzioni. Poiché una modifica delle dimensioni potrebbe essere accompagnata dalla distruzione e dalla ricostruzione dell'intera gerarchia di visualizzazione, è importante che l'utente non perda la posizione o i dati.

Cose da evitare

Evita di utilizzare valori fisici e hardware per prendere decisioni sul layout. Potrebbe essere tentadore prendere decisioni in base a un valore fisso, ma in molte situazioni questi valori non sono utili per determinare lo spazio con cui può lavorare l'interfaccia utente.

Le app potrebbero riscontrare problemi di ridimensionamento della finestra quando vengono eseguite in modalità multifinestra, in modalità Picture in picture o in finestre senza un formato, ad esempio su ChromeOS. Può anche essere presente più di un suo schermo fisico, ad esempio con un dispositivo pieghevole o con un dispositivo con più display. In tutti questi casi, le dimensioni fisiche dello schermo non sono pertinenti per decidere come visualizzare i contenuti.

Più dispositivi che mostrano finestre dell'app di dimensioni diverse.
Figura 1. Le dimensioni della finestra possono essere diverse dalle dimensioni del dispositivo fisico o del display.

Per lo stesso motivo, evitare di bloccare l'app su un orientamento o un formato specifico. Anche se il dispositivo stesso potrebbe essere in un determinato orientamento, la tua app potrebbe essere in un orientamento diverso in base esclusivamente alle dimensioni della sua finestra. Ad esempio, su un tablet in modalità Orizzontale mentre utilizzi la modalità multi-finestra, un'app può essere in verticale perché è più alta che larga.

Inoltre, evitare di provare a stabilire se il dispositivo è uno smartphone o un tablet. La definizione specifica di tablet è piuttosto soggettiva: si basa su dimensioni, proporzioni o una combinazione di dimensioni e proporzioni specifiche? Con l'emergere di nuovi fattori di forma, queste supposizioni possono cambiare e la distinzione perde importanza.

Anziché provare una delle strategie precedenti, utilizza gli intervalli di interruzione e le classi di dimensioni della finestra.

Punti di interruzione e classi di dimensioni delle finestre

La parte effettiva dello schermo allocata alla tua app è la sua finestra. Può occupare l'intero schermo o una parte dello schermo, quindi utilizza le dimensioni della finestra quando prendi decisioni di alto livello sul layout dell'app.

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

Elementi UI permanenti

Le linee guida per il layout di Material Design definiscono le regioni per barre dell'app, navigazione e contenuti. In genere, i primi due sono elementi UI permanenti nella radice (o molto vicino) della gerarchia della vista. Tieni presente che "permanente" non significa necessariamente che la visualizzazione sia sempre visibile, ma piuttosto che rimane invariata mentre altre visualizzazioni dei contenuti potrebbero muoversi o cambiare. Ad esempio, un elemento di navigazione potrebbe trovarsi in un riquadro scorrevole non visibile sullo schermo, ma il riquadro è sempre presente.

Gli elementi permanenti possono essere adattabili e di solito occupano l'intera larghezza o l'intera altezza della finestra, quindi preferisci utilizzare le classi di dimensioni per decidere dove posizionarli. In questo modo viene delineato lo spazio rimanente per i contenuti. Nel seguente snippet, l'attività utilizza una barra in basso per gli schermi compatti e una barra delle app in alto per gli schermi più grandi. I layout idonei utilizzano gli intervalli di interruzione della 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 dell'interfaccia utente permanenti, utilizza lo spazio rimanente per i contenuti, ad esempio utilizzando un NavHostFragment con il grafico di navigazione della tua app. Per ulteriori considerazioni, consulta la sezione Navigazione per UI responsive.

Assicurati che tutti i dati siano disponibili per dimensioni diverse

La maggior parte dei framework per app oggi utilizza un modello di dati separato dai componenti Android che contribuiscono all'interfaccia utente (attività, frammenti e visualizzazioni). Con Jetpack, questo ruolo viene solitamente svolto dai ViewModel, che hanno il vantaggio aggiuntivo di sopravvivere alle modifiche alla configurazione (per ulteriori informazioni, consulta la Panoramica di ViewModel).

Quando implementi un layout che si adatta a dimensioni diverse, potrebbe essere temptinge utilizzare un modello di dati diverso in base alle dimensioni correnti. Tuttavia, questo va contro il principio del flusso di dati unidirezionale. I dati devono fluire downward verso le visualizzazioni e gli eventi come le interazioni utente devono fluire verso l'alto. La creazione di una dipendenza nell'altra direzione, in cui il modello di dati dipende dalla configurazione del livello dell'interfaccia utente, complica notevolmente la situazione. Quando la dimensione dell'app cambia, devi tenere conto della conversione da un modello di dati all'altro.

Lascia invece che il tuo modello di dati accolga la classe di dimensioni più grande, in modo da poter mostrare, nascondere o riposizionare selettivamente i contenuti nell'interfaccia utente in base alla classe di dimensioni corrente. Di seguito sono riportate alcune strategie che puoi utilizzare per decidere come deve comportarsi il layout durante il passaggio da una classe di dimensioni all'altra.

Espandere i contenuti

Layout canonici: feed

Lo spazio aggiuntivo può essere un'opportunità per ingrandire i contenuti e riformattarli in modo che siano più accessibili.

Aumenta le dimensioni delle collezioni. Molte app mostrano una raccolta di elementi in un contenuto scorrevole, ad esempio un RecyclerView o un ScrollView. Se consenti a un contenitore di aumentare automaticamente di dimensioni, puoi mostrare più contenuti. Tuttavia, fai attenzione a non allungare o distorcere eccessivamente i contenuti all'interno del contenitore. Ad esempio, con un RecyclerView, valuta la possibilità di utilizzare un gestore del layout diverso, come GridLayoutManager, StaggeredGridLayoutManager o FlexboxLayout, quando la larghezza non è compatta.

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

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

Metti in evidenza un elemento hero. Se il layout ha un punto focale particolare, come un'immagine o un video, espandilo quando la finestra dell'app si allarga 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 visualizzazione secondaria, ad esempio in percentuale o applicando un rapporto di aspetto, e per posizionare le visualizzazioni secondarie rispetto a se stessa o ad altre visualizzazioni secondarie. Scopri di più su tutte queste funzionalità in Creare un'interfaccia utente adattabile con ConstraintLayout.

Mostra i contenuti comprimibili per impostazione predefinita. Se c'è spazio disponibile, mostra contenuti che altrimenti sarebbero accessibili solo tramite un'interazione aggiuntiva dell'utente, ad esempio tocchi, scorrimento o gesti. Ad esempio, i contenuti che vengono visualizzati in un'interfaccia a schede in modalità compatta potrebbero essere riorganizzati in colonne o in un elenco quando è disponibile più spazio.

Aumentare i margini. Se lo spazio è così ampio che non riesci a trovare una combinazione 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 spaziature naturali.

In alternativa, un componente a schermo intero può trasformarsi in un'UI di finestra di dialogo scorrevole. Questa opzione è particolarmente adatta quando il componente richiede un'attenzione esclusiva per svolgere un'attività immediata dell'utente, ad esempio scrivere un'email o creare un evento nel calendario.

Uno smartphone standard che mostra una finestra di dialogo a schermo intero e uno smartphone pieghevole aperto che mostra la stessa finestra di dialogo come finestra mobile.
Figura 3. Finestra di dialogo a schermo intero trasformata in una finestra di dialogo standard con larghezza media ed espansa.

Aggiungi contenuti

Layout canonici: riquadro di supporto, visualizzazione elenco dettagliata

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

Un aspetto importante da considerare è dove posizionare questi contenuti quando non c'è abbastanza spazio per mostrare il riquadro. Ecco alcune alternative da esplorare:

  • Riquadro laterale sul bordo posteriore utilizzando DrawerLayout
  • Cassetto inferiore che utilizza BottomSheetBehavior
  • Menu o finestra popup accessibile toccando un'icona del menu
Figura 4. Modi alternativi per presentare contenuti aggiuntivi in un riquadro di supporto.

Creare un layout a due riquadri. Gli schermi di grandi dimensioni potrebbero mostrare una combinazione di funzionalità che normalmente vengono visualizzate separatamente su schermi più piccoli. Un modello 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. Invece di ingrandire l'elenco per gli schermi più grandi, utilizza la visualizzazione elenco dettagliata per mostrare entrambe le funzionalità una accanto all'altra in un layout a due riquadri. A differenza di un riquadro di supporto, il riquadro dei dettagli di una visualizzazione elenco è un elemento autonomo che può essere mostrato in modo indipendente su schermi più piccoli.

Utilizza il SlidingPaneLayout widget dedicato per implementare una visualizzazione dettagliata dell'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. Lo spazio rimanente può essere distribuito utilizzando layout_weight. Se non c'è abbastanza spazio, ogni riquadro utilizza l'intera larghezza del layout e il riquadro dei dettagli scompare dallo schermo o si sovrappone al riquadro dell'elenco.

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

L'articolo Creare un layout a due riquadri contiene maggiori dettagli sull'utilizzo di SlidingPaneLayout. Tieni inoltre presente che questo pattern può influire sulla struttura del grafo di navigazione (consulta Navigazione per UI adattabili).

Risorse aggiuntive