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 sulle visualizzazioni di supportare tutte le dimensioni, gli orientamenti e le configurazioni di visualizzazione, incluse le configurazioni ridimensionabili come la modalità multi-finestra.

Design adattabile

Il primo passaggio per supportare una varietà di fattori di forma dei dispositivi consiste nel creare un layout adattabile alle variazioni di 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 le dimensioni 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 del layout consente di trascinare nuove viste nel layout, applicare vincoli relativi alle viste principali e affini e impostare le proprietà delle viste, il tutto senza modificare manualmente il codice XML.

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

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

Larghezza e altezza adattabili

Per assicurarti che il tuo layout sia adattabile alle diverse dimensioni del display, utilizza wrap_content, match_parent o 0dp (match constraint) per i componenti di larghezza e altezza dei componenti della vista anziché i valori hardcoded:

  • wrap_content: la visualizzazione imposta le proprie dimensioni in modo che si adattino 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 visualizzazione occupa tutto lo spazio disponibile all'interno dei relativi vincoli.

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 vengono regolate in base alle variazioni della larghezza del display in base all'orientamento del dispositivo.

Figura 4. Un TextView adattabile.

TextView imposta la larghezza per riempire tutto lo spazio disponibile (match_parent) e l'altezza sullo spazio richiesto dall'altezza del testo contenuto (wrap_content), il che consente alla visualizzazione di adattarsi a diverse dimensioni di visualizzazione e quantità di testo.

Se utilizzi una LinearLayout, puoi anche espandere le visualizzazioni secondarie in base alla ponderazione del layout in modo che le visualizzazioni riempiano in modo proporzionale 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 visualizzazione, rallentando le prestazioni dell'interfaccia utente.

ConstraintLayout è in grado di creare quasi tutti i layout possibili con LinearLayout senza alcun impatto sulle prestazioni, quindi converti la versione nidificata di LinearLayout in ConstraintLayout. Quindi puoi definire layout ponderati con catene di vincoli.

Design adattivo

Il layout dell'app deve sempre adattarsi alle diverse dimensioni del display. Tuttavia, anche un layout adattabile non può offrire la migliore esperienza utente su ogni dispositivo o visualizzazione in modalità multi-finestra. Ad esempio, l'interfaccia utente progettata per uno smartphone probabilmente non offre un'esperienza utente ottimale su un tablet. Il design adattivo fornisce layout alternativi ottimizzati per diverse dimensioni di visualizzazione.

SlidingPaneLayout per le UI dei dettagli dell'elenco

Generalmente, una UI con i dettagli di un elenco fornisce 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 un elemento nell'elenco è selezionato, le relative informazioni vengono visualizzate nel riquadro dei dettagli senza modificare l'interfaccia utente: i due riquadri rimangono affiancati. Tuttavia, su schermi di piccole dimensioni, i due riquadri vengono visualizzati separatamente e ciascuno occupa l'intera area di visualizzazione. Quando viene selezionato un elemento nel riquadro dell'elenco, il riquadro dei dettagli (contenente le informazioni sull'elemento selezionato) sostituisce il riquadro dell'elenco. La navigazione indietro sostituisce il riquadro dei dettagli con l'elenco.

SlidingPaneLayout gestisce la logica per determinare quale delle due esperienze utente è appropriata per l'attuale dimensione della finestra:

<?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 visualizzare entrambe le viste, i riquadri vengono visualizzati affiancati. Tuttavia, se la larghezza della finestra è inferiore a 580 dp, i riquadri scorrono uno sull'altro per occupare singolarmente l'intera finestra dell'app.

Se la larghezza della finestra è superiore alla larghezza minima totale specificata (580 dp), è possibile utilizzare layout_weight valori 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 visualizzazione.

Risorse di layout alternativi

Per adattare il design dell'interfaccia utente a dimensioni di visualizzazione molto variabili, utilizza layout alternativi identificati dai qualificatori delle risorse.

Figura 5. La stessa app che utilizza layout diversi per display di dimensioni diverse.

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

I qualificatori di configurazione rappresentano lo spazio di visualizzazione visibile disponibile per la UI della tua app. Quando seleziona il layout per l'app, il sistema prende in considerazione qualsiasi decorazione del sistema (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 l'ottimizzazione per schermi diversi in Sviluppare un'interfaccia utente con Visualizzazioni.

Qualificatore di larghezza più piccolo

Il qualificatore delle dimensioni dello schermo 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 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 smartphone e tablet, creando diverse versioni del file in diverse directory:

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, pertanto consente di specificare le dimensioni di visualizzazione complessive disponibili per il layout.

Ecco in che modo altri valori di larghezza più piccoli 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 seguente fornisce una visione più dettagliata di come le diverse larghezze dp dei dp dello schermo corrispondono a dimensioni e orientamenti diversi.

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 tiene conto della densità dei pixel (non della risoluzione dei pixel non elaborati).

Le dimensioni specificate mediante qualificatori di risorse, come la larghezza minima, non corrispondono alle dimensioni effettive dello schermo. ma specificano la larghezza o l'altezza in unità dp disponibili per la 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 la tua 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 di configurazione con le nuove dimensioni della finestra, che consente al sistema di selezionare un file di layout appropriato. Di conseguenza, le dimensioni dei qualificatori delle risorse dichiarate devono specificare solo lo spazio necessario per l'app. Il sistema prende in considerazione qualsiasi spazio utilizzato dall'interfaccia utente di sistema quando fornisci spazio per il layout.

Qualificatore larghezza disponibile

Invece di modificare il layout in base alla larghezza minima del display, ti consigliamo di modificarlo in base alla larghezza o all'altezza disponibili. Ad esempio, puoi utilizzare un layout a due riquadri ogni volta che lo schermo fornisce almeno 600 dp di larghezza, che può variare a seconda dell'orientamento del dispositivo, orizzontale o verticale. In questo 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 ti preoccupa per la tua app, puoi utilizzare il qualificatore altezza disponibile. Ad esempio, layout-h600dp per gli schermi con almeno 600 dp di altezza dello schermo.

Qualificatori di orientamento

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

Per farlo, puoi aggiungere i qualificatori port o land ai nomi delle directory di layout. Assicurati solo che i qualificatori di orientamento siano successivi ai qualificatori di taglia. 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 la panoramica delle risorse delle 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 prevede sempre una classe di dimensioni delle finestre per la larghezza e una classe per l'altezza.

Per applicare i layout adattivi in modo programmatico:

  • Creare risorse di layout in base ai punti di interruzione della classe delle dimensioni delle finestre
  • Calcola le classi di dimensioni delle finestre 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 sulle classi di dimensioni delle finestre, vedi Supportare schermi di dimensioni diverse.

Componenti dell'interfaccia utente modulari mediante frammenti

Quando progetti la tua app per diverse dimensioni di visualizzazione, utilizza i frammenti per estrarre la logica dell'interfaccia utente in componenti separati e assicurarti di non duplicare inutilmente il comportamento dell'interfaccia utente tra le varie attività. Dopodiché puoi combinare i frammenti per creare layout multi-riquadro su schermi di grandi dimensioni oppure puoi posizionare i frammenti in attività separate su schermi piccoli.

Ad esempio, il pattern elenco-dettagli (vedi SlidingPaneLayout sopra) potrebbe essere implementato con un frammento contenente l'elenco e un altro frammento contenente i dettagli dell'elemento dell'elenco. Su schermi di grandi dimensioni, i frammenti potevano essere visualizzati affiancati; su schermi piccoli, individualmente, riempivano lo schermo.

Per saperne di più, consulta la panoramica sui frammenti.

Incorporamento delle attività

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

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

Puoi stabilire la modalità di visualizzazione delle attività nell'applicazione creando un file di configurazione XML che il sistema utilizza per determinare la presentazione appropriata in base alle dimensioni del display. In alternativa, puoi effettuare chiamate all'API Jetpack WindowManager.

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

Per ulteriori informazioni, consulta Incorporamento delle attività.

Dimensioni e proporzioni dello schermo

Testa la tua app su una serie di dimensioni e proporzioni dello schermo diverse per assicurarti che l'interfaccia utente venga scalata 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, ad esempio 21:9 quando sono piegati, a proporzioni quadrate di 1:1 quando sono piegati.

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

Figura 7. Varie proporzioni dello schermo.

Se non hai accesso a dispositivi per tutte le diverse dimensioni degli schermi che desideri testare, puoi utilizzare l'emulatore Android per emulare quasi tutte le dimensioni degli schermi.

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 di Google.

Risorse aggiuntive