Design adattabile/adattivo con visualizzazioni

Prova Compose
Jetpack Compose è il toolkit per la UI consigliato per Android. Scopri come utilizzare i layout adattabili in Compose.

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

Responsive design

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

ConstraintLayout

Il modo migliore per creare un layout reattivo è utilizzare ConstraintLayout come layout di base per la tua UI. ConstraintLayout ti consente di specificare la posizione e le dimensioni di ogni visualizzazione in base alle relazioni spaziali con le altre visualizzazioni nel layout. Tutte le visualizzazioni possono quindi essere spostate e ridimensionate insieme man mano che lo spazio di visualizzazione cambia.

Il modo più semplice per creare un layout con ConstraintLayout è utilizzare l'editor di layout in Android Studio. Layout Editor ti consente di trascinare nuove visualizzazioni nel layout, applicare vincoli relativi alle visualizzazioni padre e fratello e impostare le proprietà delle visualizzazioni, il tutto senza modificare manualmente alcun XML.

Figura 3. Il Layout Editor in Android Studio che mostra un ConstraintLayout.

Per saperne di più, consulta Creare un'interfaccia utente reattiva con ConstraintLayout.

Larghezza e altezza adattabili

Per assicurarti che il layout sia reattivo a diverse dimensioni di visualizzazione, utilizza wrap_content, match_parent o 0dp (match constraint) per la larghezza e l'altezza dei componenti della visualizzazione anziché valori hardcoded:

  • wrap_content: La visualizzazione imposta le proprie dimensioni in modo che si adattino ai contenuti che contiene.
  • match_parent: la visualizzazione si espande il più possibile all'interno della vista genitore.
  • 0dp (match constraint): in un ConstraintLayout, simile a match_parent. La visualizzazione occupa tutto lo spazio disponibile all'interno dei vincoli della visualizzazione.

Ad esempio:

<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 TextView reattivo.

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

Se utilizzi un LinearLayout, puoi anche espandere le viste secondarie in base al peso del layout in modo che le viste riempiano proporzionalmente lo spazio disponibile. Tuttavia, l'utilizzo di pesi in un LinearLayout nidificato richiede al sistema di eseguire più passaggi di layout per determinare le dimensioni di ogni visualizzazione, rallentando le prestazioni dell'interfaccia utente.

ConstraintLayout può creare quasi tutti i layout possibili con LinearLayout senza influire sul rendimento, quindi converti i LinearLayout nidificati in ConstraintLayout. Poi puoi definire layout ponderati con catene di vincoli.

Design adattivo

Il layout dell'app deve sempre essere adattabile a diverse dimensioni del display. Tuttavia, anche un layout adattabile non può fornire la migliore esperienza utente su ogni dispositivo o visualizzazione in modalità multi-finestra. Ad esempio, l'UI che hai progettato per uno smartphone probabilmente non offre un'esperienza utente ottimale su un tablet. Il design adattabile fornisce layout alternativi ottimizzati per diverse dimensioni di visualizzazione.

SlidingPaneLayout per le UI list-detail

Un'interfaccia utente elenco-dettagli in genere offre un'esperienza utente diversa su schermi di dimensioni diverse. Sugli schermi di grandi dimensioni, i riquadri elenco e dettagli sono generalmente affiancati. Quando un elemento dell'elenco viene selezionato, le informazioni sull'elemento vengono visualizzate nel riquadro dei dettagli senza modificare l'interfaccia utente. I due riquadri rimangono uno accanto all'altro. Tuttavia, sugli schermi piccoli, i due riquadri vengono visualizzati separatamente, ciascuno occupa l'intera area di visualizzazione. Quando viene selezionato un elemento nel riquadro dell'elenco, il riquadro dei dettagli (contenente le informazioni dell'elemento selezionato) sostituisce il riquadro dell'elenco. La navigazione a ritroso sostituisce il riquadro dei dettagli con l'elenco.

SlidingPaneLayout gestisce la logica per determinare quale delle due esperienze utente è appropriata per le dimensioni attuali 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 (almeno 580 dp di larghezza) da visualizzare entrambe le visualizzazioni, i riquadri vengono visualizzati uno accanto all'altro. 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 è maggiore della larghezza minima totale specificata (580 dp), i valori layout_weight possono essere utilizzati per dimensionare i due riquadri in modo proporzionale. Nell'esempio, il riquadro dell'elenco ha sempre una larghezza di 280 dp perché non ha un peso. Il riquadro dei dettagli, tuttavia, riempie sempre lo spazio orizzontale oltre i 580 dp a causa dell'impostazione layout_weight della visualizzazione.

Risorse di layout alternative

Per adattare la progettazione dell'interfaccia utente a dimensioni di visualizzazione molto diverse, utilizza layout alternativi identificati dai qualificatori delle risorse.

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

Puoi fornire layout adattivi e specifici per lo schermo creando directory res/layout/ aggiuntive nel codice sorgente dell'app. Crea 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 dell'app. Il sistema tiene conto di eventuali decorazioni del sistema (come la barra di navigazione) e delle modifiche alla configurazione della finestra (come la modalità multifinestra) quando seleziona il layout per la tua app.

Per creare layout alternativi in Android Studio, consulta Utilizzare le varianti di layout per ottimizzare per schermi diversi in Sviluppare una UI con le visualizzazioni.

Qualificatore di larghezza minima

Il qualificatore delle dimensioni dello schermo smallest width ti 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 di dp, Android ti consente di creare layout progettati per dimensioni di visualizzazione specifiche senza preoccuparti delle diverse densità di pixel.

Ad esempio, puoi creare un layout denominato main_activity ottimizzato per smartphone 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 più piccolo specifica il più piccolo dei due lati del display, indipendentemente dall'orientamento attuale del dispositivo, quindi è un modo per specificare le dimensioni di visualizzazione complessive disponibili per il layout.

Ecco come gli altri valori di larghezza minima corrispondono alle dimensioni tipiche dello schermo:

  • 320 dp: schermo piccolo dello smartphone (240 x 320 ldpi, 320 x 480 mdpi, 480 x 800 hdpi e così via)
  • 480 dp: schermo dello smartphone grande ~5" (480 x 800 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 mostra in modo più dettagliato come le diverse larghezze dp dello schermo corrispondono a diverse dimensioni e orientamenti dello schermo.

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

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à di pixel (non della risoluzione in pixel grezzi).

Le dimensioni specificate utilizzando qualificatori di risorse come la larghezza più piccola non sono le dimensioni effettive dello schermo. Le dimensioni specificano invece la larghezza o l'altezza in unità dp disponibili per la finestra dell'app. Il sistema Android potrebbe utilizzare parte dello schermo per la UI di sistema (ad esempio la barra di sistema nella parte inferiore dello schermo o la barra di stato nella parte superiore), quindi parte dello schermo potrebbe non essere disponibile per il layout. Se la tua app viene utilizzata in modalità multi-finestra, ha accesso solo alle dimensioni della finestra che la contiene. Quando la finestra viene ridimensionata, viene attivata una modifica della configurazione con le nuove dimensioni della finestra, il che consente al sistema di selezionare un file di layout appropriato. Pertanto, le dimensioni dei qualificatori delle risorse che dichiari devono specificare solo lo spazio necessario alla tua app. Il sistema tiene conto di qualsiasi spazio utilizzato dall'interfaccia utente di sistema quando fornisce spazio per il layout.

Qualificatore di larghezza disponibile

Anziché modificare il layout in base alla larghezza più piccola del display, potresti modificarlo in base alla larghezza o all'altezza disponibile. Ad esempio, potresti voler utilizzare un layout a due riquadri ogni volta che lo schermo offre almeno 600 dp di larghezza, che potrebbero cambiare a seconda che il dispositivo sia in orientamento orizzontale o verticale. In questo caso, devi utilizzare il qualificatore larghezza disponibile nel seguente modo:

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 è un problema per la tua app, puoi utilizzare il qualificatore altezza disponibile. Ad esempio, layout-h600dp per schermi con almeno 600 dp di altezza dello schermo.

Qualificatori di orientamento

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

A questo scopo, puoi aggiungere i qualificatori port o land ai nomi delle directory di layout. Assicurati solo che i qualificatori di orientamento vengano dopo i qualificatori di dimensioni. Ad esempio:

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 dell'app.

Classi di dimensioni dello schermo

Le classi di dimensioni della finestra sono punti di interruzione del viewport che ti aiutano a 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, in modo che la tua app abbia sempre una classe di dimensioni della finestra per la larghezza e una classe di dimensioni della finestra per l'altezza.

Per applicare in modo programmatico i layout adattivi:

  • Crea risorse di layout in base ai punti di interruzione delle classi di dimensioni della finestra
  • Calcola le classi di dimensioni della finestra di larghezza e altezza della tua app utilizzando la funzione WindowSizeClass#compute() della libreria Jetpack WindowManager.
  • Gonfia la risorsa di layout per le classi di dimensioni della finestra corrente

Per saperne di più, consulta la sezione Classi di dimensioni delle finestre.

Componenti UI modularizzati che utilizzano i fragment

Quando progetti la tua app per più dimensioni di visualizzazione, utilizza i fragment per estrarre la logica dell'interfaccia utente in componenti separati per assicurarti di non duplicare inutilmente il comportamento dell'interfaccia utente tra le attività. Puoi quindi combinare i frammenti per creare layout a più riquadri su schermi grandi 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 della voce di elenco. Sugli schermi di grandi dimensioni, i frammenti potrebbero essere visualizzati uno accanto all'altro; sugli schermi piccoli, singolarmente, riempiendo lo schermo.

Per saperne di più, consulta la panoramica dei fragment.

Incorporamento attività

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

L'incorporamento di attività mostra più attività o più istanze della stessa attività contemporaneamente nella finestra delle attività di un'applicazione. Su schermi di grandi dimensioni, le attività possono essere visualizzate una accanto all'altra; su schermi di piccole dimensioni, una sopra l'altra.

Per determinare la modalità di visualizzazione delle attività dell'app, crea 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, l'impilamento e la rimozione delle attività quando il dispositivo ruota o si piega e si apre.

Per saperne di più, consulta Incorporamento dell'attività.

Dimensioni dello schermo e proporzioni

Testa la tua app su una serie di dimensioni dello schermo e proporzioni per assicurarti che la UI 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 aperti.

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

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 test su un dispositivo reale ma non lo hai, puoi utilizzare Firebase Test Lab per accedere ai dispositivi in un data center Google.

Risorse aggiuntive