Design adattabile/adattivo con visualizzazioni

I layout adattabili/adattivi offrono un'esperienza utente ottimizzata indipendentemente dalle dimensioni dello schermo. Implementa layout adattabili/adattivi per consentire alla tua app basata sulla visualizzazione di supportare tutte le dimensioni, gli orientamenti e le configurazioni, incluse le configurazioni ridimensionabili come la modalità multi-finestra.

Design adattabile

Il primo passaggio per supportare una varietà di fattori di forma dei dispositivi è creare un layout reattivo alle variazioni dello spazio di visualizzazione disponibile per la tua app.

Layout vincolo

Il modo migliore per creare un layout adattabile è utilizzare ConstraintLayout come layout di base per l'interfaccia utente. ConstraintLayout consente di specificare la posizione e la dimensione di ogni vista in base alle relazioni spaziali con altre viste del layout. Tutte le viste possono quindi essere spostate e ridimensionate insieme quando lo spazio di visualizzazione cambia.

Il modo più semplice per creare un layout con ConstraintLayout è usare l'Editor layout in Android Studio. L'Editor di layout ti consente di trascinare nuove viste nel layout, applicare vincoli relativi alle viste principali e gemelle e impostare le proprietà delle viste, il tutto senza modificare manualmente i file XML.

Figura 3. Editor di layout in Android Studio che mostra un ConstraintLayout.

Per ulteriori informazioni, consulta Creare un'interfaccia utente adattabile con ConstraintLayout.

Larghezza e altezza adattabili

Per assicurarti che il tuo layout sia adattabile alle diverse dimensioni di visualizzazione, usa wrap_content, match_parent o 0dp (match constraint) per la larghezza e l'altezza dei componenti della visualizzazione anziché i valori impostati come hardcoded:

  • wrap_content: le dimensioni della visualizzazione vengono impostate in modo da adattarsi ai contenuti inclusi.
  • match_parent: la vista si espande il più possibile all'interno della vista principale.
  • 0dp (match constraint): in un ConstraintLayout, simile a match_parent. La vista occupa tutto lo spazio disponibile entro i vincoli della vista.

Ecco alcuni esempi:

<TextView
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:text="@string/lorem_ipsum" />

La figura 4 mostra come la larghezza e l'altezza di TextView si adattano al variare della larghezza del display in base all'orientamento del dispositivo.

Figura 4. Un elemento TextView adattabile.

L'elemento TextView imposta la larghezza in modo da riempire tutto lo spazio disponibile (match_parent) e l'altezza allo spazio richiesto esattamente dall'altezza del testo contenuto (wrap_content), in modo che la visualizzazione si adatti a dimensioni di visualizzazione e quantità di testo diverse.

Se utilizzi una LinearLayout, puoi anche espandere le visualizzazioni secondarie in base alla peso del layout, in modo che le visualizzazioni riempiano proporzionalmente lo spazio disponibile. Tuttavia, l'utilizzo delle ponderazioni in un elemento LinearLayout nidificato richiede che il sistema esegua più passaggi di layout per determinare le dimensioni di ogni vista, rallentando le prestazioni dell'interfaccia utente.

ConstraintLayout può creare quasi tutti i layout possibili con LinearLayout senza influire sulle prestazioni, quindi converti il tuo asset nidificato LinearLayout in ConstraintLayout. Quindi puoi definire layout ponderati con catene di vincoli.

Design adattivo

Il layout dell'app deve sempre adattarsi alle diverse dimensioni dei display. Tuttavia, nemmeno un layout adattabile non è in grado di offrire la migliore esperienza utente su ogni dispositivo o sulla visualizzazione in modalità multi-finestra. Ad esempio, l'interfaccia utente che hai progettato per uno smartphone probabilmente non offre un'esperienza utente ottimale su un tablet. Il design adattivo offre layout alternativi ottimizzati per diverse dimensioni di visualizzazione.

SlidingPaneLayout per le UI dei dettagli dell'elenco

Una UI dei dettagli di un elenco fornisce in genere un'esperienza utente diversa su schermi di dimensioni diverse. Sugli schermi di grandi dimensioni, i riquadri dell'elenco e dei dettagli di solito sono affiancati. Quando è selezionato un elemento nell'elenco, le relative informazioni vengono visualizzate nel riquadro dei dettagli senza modificare l'interfaccia utente: i due riquadri rimangono uno accanto all'altro. Sugli schermi di piccole dimensioni, invece, i due riquadri vengono visualizzati separatamente e ognuno occupa l'intera area di visualizzazione. Quando è selezionato un elemento nel riquadro dell'elenco, il riquadro dei dettagli (contenente le informazioni sull'elemento selezionato) lo sostituisce. La barra di navigazione posteriore sostituisce il riquadro dei dettagli con l'elenco.

SlidingPaneLayout gestisce la logica per determinare quale delle due esperienze utente è appropriata per le dimensioni della finestra corrente:

<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <androidx.recyclerview.widget.RecyclerView
        android:id="@+id/recycler_view"
        android:layout_width="280dp"
        android:layout_height="match_parent"
        android:layout_gravity="start" />

    <androidx.fragment.app.FragmentContainerView
        android:id="@+id/nav_host_fragment"
        android:name="androidx.navigation.fragment.NavHostFragment"
        android:layout_width="300dp"
        android:layout_height="match_parent"
        android:layout_weight="1"
        app:defaultNavHost="true"
        app:navGraph="@navigation/item_navigation" />

</androidx.slidingpanelayout.widget.SlidingPaneLayout>

Gli attributi layout_width e layout_weight delle due viste contenute in SlidingPaneLayout determinano il comportamento di SlidingPaneLayout. Nell'esempio, se la finestra è abbastanza grande (larga almeno 580 dp) da mostrare entrambe le viste, i riquadri vengono mostrati affiancati. Tuttavia, se la larghezza della finestra è inferiore a 580 dp, i riquadri scorrono uno sull'altro in modo da occupare singolarmente l'intera finestra dell'app.

Se la larghezza della finestra è superiore alla larghezza minima totale specificata (580 dp), è possibile utilizzare i valori layout_weight per ridimensionare i due riquadri in modo proporzionale. Nell'esempio, il riquadro dell'elenco è sempre largo 280 dp perché non ha una ponderazione. Tuttavia, il riquadro dei dettagli riempie sempre qualsiasi spazio orizzontale oltre i 580 dp per via dell'impostazione layout_weight della vista.

Risorse di layout alternative

Per adattare il design della tua UI a dimensioni di visualizzazione molto diverse, utilizza layout alternativi identificati dai qualificatori delle risorse.

Figura 5. La stessa app con layout diversi per dimensioni di display differenti.

Puoi fornire layout adattivi specifici per schermo creando directory res/layout/ aggiuntive nel codice sorgente dell'app. Creare una directory per ogni configurazione dello schermo che richiede un layout diverso. Quindi aggiungi un qualificatore di configurazione dello schermo al nome della directory layout (ad esempio, layout-w600dp per gli schermi con 600 dp di larghezza disponibile).

I qualificatori di configurazione rappresentano lo spazio di visualizzazione visibile disponibile per la UI della tua app. Quando selezioni il layout per la tua app, il sistema tiene conto di eventuali decorazioni (ad esempio la barra di navigazione) e modifiche alla configurazione delle finestre (ad esempio la modalità multi-finestra).

Per creare layout alternativi in Android Studio, consulta Utilizzare le varianti di layout per ottimizzare le campagne per schermi diversi in Sviluppare un'interfaccia utente con Visualizzazioni.

Qualificatore larghezza minima

Il qualificatore per le dimensioni dello schermo con larghezza minima consente di fornire layout alternativi per i display con una larghezza minima misurata in pixel indipendenti dalla densità (dp).

Descrivendo le dimensioni dello schermo come misura del dp, Android ti consente di creare layout progettati per dimensioni di visualizzazione specifiche senza preoccuparsi delle diverse densità di pixel.

Ad esempio, puoi creare un layout denominato main_activity ottimizzato per telefoni e tablet, creando versioni diverse del file in directory diverse:

res/layout/main_activity.xml           # For phones (smaller than 600dp smallest width)
res/layout-sw600dp/main_activity.xml   # For 7" tablets (600dp wide or wider)

Il qualificatore di larghezza minima specifica il più piccolo dei due lati del display, indipendentemente dall'orientamento corrente del dispositivo, quindi consente di specificare le dimensioni di visualizzazione complessive disponibili per il layout.

Ecco come i valori più piccoli di larghezza corrispondono alle dimensioni tipiche degli schermi:

  • 320 dp: schermo di un telefono piccolo (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi e così via)
  • 480dp: Schermo del telefono grande ~5" (480x800 mdpi)
  • 600 dp: tablet da 7" (600 x 1024 mdpi)
  • 720 dp: tablet da 10" (720 x 1280 mdpi, 800 x 1280 mdpi e così via)

La figura che segue fornisce una visione più dettagliata di come le diverse larghezze dei dp dp dello schermo corrispondono a dimensioni e orientamenti diversi dello schermo.

Figura 6. Punti di interruzione della larghezza consigliati per supportare schermi di dimensioni diverse.

I valori per il qualificatore larghezza minima sono dp, perché ciò che conta è la quantità di spazio di visualizzazione disponibile dopo che il sistema ha preso in considerazione la densità dei pixel (non la risoluzione in pixel non elaborati).

Le dimensioni specificate utilizzando i qualificatori di risorse, come la larghezza minima, non corrispondono alle dimensioni effettive dello schermo. Le dimensioni specificano invece la larghezza o l'altezza in unità dp disponibili nella finestra dell'app. Il sistema Android potrebbe utilizzare parte dello schermo per l'interfaccia utente di sistema (ad esempio la barra di sistema nella parte inferiore dello schermo o la barra di stato in alto), pertanto parte dello schermo potrebbe non essere disponibile per il tuo layout. Se l'app viene utilizzata in modalità multi-finestra, ha accesso soltanto alle dimensioni della finestra che la contiene. Quando la finestra viene ridimensionata, attiva una modifica della configurazione con le nuove dimensioni della finestra, che consente al sistema di selezionare un file di layout appropriato. Pertanto, le dimensioni del qualificatore delle risorse dichiarate devono specificare solo lo spazio necessario per la tua app. Il sistema prende in considerazione qualsiasi spazio utilizzato dall'interfaccia utente di sistema quando fornisci spazio per il layout.

Qualificatore larghezza disponibile

Anziché cambiare il layout in base alla larghezza minima del display, ti consigliamo di modificarlo in base alla larghezza o all'altezza disponibili. Ad esempio, è possibile utilizzare un layout a due riquadri ogni volta che lo schermo offre almeno 600 dp di larghezza, che può variare a seconda dell'orientamento orizzontale o verticale del dispositivo. In tal caso, devi utilizzare il qualificatore larghezza disponibile come segue:

res/layout/main_activity.xml         # For phones (smaller than 600dp available width)
res/layout-w600dp/main_activity.xml  # For 7" tablets or any screen with 600dp available width
                                     # (possibly landscape phones)

Se l'altezza disponibile rappresenta un problema per la tua app, puoi utilizzare il qualificatore altezza disponibile. Ad esempio, layout-h600dp per schermi con almeno 600 dp di altezza.

Qualificatori di orientamento

Anche se potresti essere in grado di supportare tutte le varianti di dimensioni utilizzando solo combinazioni dei qualificatori larghezza minima e larghezza disponibile, potresti anche modificare l'esperienza utente quando l'utente passa dall'orientamento verticale a quello orizzontale e viceversa.

In questo caso, puoi aggiungere i qualificatori port o land ai nomi delle directory di layout. Assicurati solo che i qualificatori di orientamento siano successivi ai qualificatori delle dimensioni. Ecco alcuni esempi:

res/layout/main_activity.xml                # For phones
res/layout-land/main_activity.xml           # For phones in landscape
res/layout-sw600dp/main_activity.xml        # For 7" tablets
res/layout-sw600dp-land/main_activity.xml   # For 7" tablets in landscape

Per ulteriori informazioni su tutti i qualificatori di configurazione dello schermo, consulta Panoramica delle risorse per le app.

Classi di dimensioni della finestra

Le classi di dimensioni delle finestre sono punti di interruzione dell'area visibile che consentono di creare layout adattivi. I punti di interruzione identificano l'area di visualizzazione disponibile per la tua app come compatta, media o espansa. Larghezza e altezza sono specificate separatamente, pertanto la tua app ha sempre una classe di dimensione della finestra per la larghezza e una classe di dimensione della finestra per l'altezza.

Per applicare i layout adattivi a livello di programmazione:

  • Crea risorse di layout in base ai punti di interruzione di classe delle dimensioni delle finestre
  • Calcola le classi delle dimensioni della finestra di larghezza e altezza dell'app utilizzando la funzione WindowSizeClass#compute() della libreria Jetpack WindowManager
  • Aumenta la risorsa di layout per le classi di dimensioni delle finestre correnti

Per ulteriori informazioni, consulta Classi relative alle dimensioni delle finestre.

Componenti dell'interfaccia utente modulari utilizzando frammenti

Quando progetti l'app per più dimensioni di visualizzazione, utilizza i frammenti per estrarre la logica dell'interfaccia utente in componenti separati per assicurarti di non duplicare inutilmente il comportamento dell'interfaccia utente tra le attività. Dopodiché puoi combinare i frammenti per creare layout a più riquadri su schermi di grandi dimensioni oppure puoi inserire frammenti in attività separate su schermi piccoli.

Ad esempio, il pattern dei dettagli elenco (vedi SlidingPaneLayout sopra) potrebbe essere implementato con un frammento contenente l'elenco e un altro frammento contenente i dettagli degli elementi dell'elenco. Su schermi di grandi dimensioni, i frammenti potevano essere visualizzati uno accanto all'altro; su schermi piccoli, singolarmente, riempiendo lo schermo.

Per scoprire di più, vedi la panoramica sui frammenti.

Incorporamento delle attività

Se la tua app è composta da più attività, l'incorporamento delle attività ti consente di creare facilmente un'interfaccia utente adattiva.

L'incorporamento delle attività mostra contemporaneamente più attività o più istanze della stessa attività nella finestra delle attività di un'applicazione. Su schermi di grandi dimensioni, le attività possono essere visualizzate affiancate; su schermi piccoli, impilati uno sopra l'altro.

Puoi determinare in che modo la tua app visualizza le attività creando un file di configurazione XML che il sistema utilizza per determinare la presentazione appropriata in base alle dimensioni di visualizzazione. In alternativa, puoi effettuare chiamate all'API Jetpack WindowManager.

L'incorporamento delle attività supporta i cambiamenti di orientamento del dispositivo e i dispositivi pieghevoli, nonché le attività di stack e annullamento dell'impilamento durante la rotazione, il piegamento e l'apertura del dispositivo.

Per ulteriori informazioni, consulta la sezione Incorporamento delle attività.

Dimensioni dello schermo e proporzioni

Testa la tua app su diverse dimensioni dello schermo e proporzioni per assicurarti che la tua UI venga ridimensionata correttamente.

Android 10 (livello API 29) e versioni successive supportano un'ampia gamma di proporzioni. I fattori di forma pieghevoli possono variare da schermi alti e stretti, come 21:9 quando è piegato, a proporzioni quadrate di 1:1 quando è aperto.

Per garantire la compatibilità con il maggior numero possibile di dispositivi, testa le tue app per il maggior numero possibile di proporzioni tra le seguenti:

Figura 7. Varie proporzioni dello schermo.

Se non hai accesso a dispositivi per tutte le diverse dimensioni dello schermo che vuoi testare, puoi utilizzare l'emulatore Android per emulare quasi tutte le dimensioni dello schermo.

Se preferisci eseguire il test su un dispositivo reale ma non hai il dispositivo, puoi utilizzare Firebase Test Lab per accedere ai dispositivi in un data center Google.

Risorse aggiuntive