Utilizzare le classi di dimensioni delle finestre

Prova la funzionalità Scrivi
Jetpack Compose è il toolkit per l'interfaccia utente consigliato per Android. Scopri come utilizzare le classi di dimensioni della finestra in Compose.

Le classi di dimensioni della finestra sono un insieme di punti di interruzione del viewport che ti aiutano a progettare, sviluppare e testare layout adattabili/responsive. I punti di interruzione bilanciano la semplicità del layout con la flessibilità di ottimizzare l'app per casi unici.

Le classi di dimensioni della finestra classificano l'area di visualizzazione disponibile per la tua app come compatta, media, espansa, grande o molto grande. La larghezza e l'altezza disponibili sono classificate separatamente, quindi in qualsiasi momento la tua app ha due classi di dimensioni della finestra: una per la larghezza e una per l'altezza. La larghezza disponibile è in genere più importante dell'altezza disponibile a causa dell'ubiquità dello scorrimento verticale, quindi la classe di dimensioni della finestra di larghezza è probabilmente più pertinente all'interfaccia utente della tua app.

Figura 1. Rappresentazioni delle classi di dimensioni della finestra basate sulla larghezza.
Figura 2. Rappresentazioni delle classi di dimensioni delle finestre basate sull'altezza.

Come illustrato nelle figure, i punti di interruzione ti consentono di continuare a pensare ai layout in termini di dispositivi e configurazioni. Ogni punto di interruzione della classe di dimensioni rappresenta un caso maggioritario per gli scenari tipici dei dispositivi, che può essere un utile punto di riferimento quando pensi alla progettazione dei layout basati sui punti di interruzione.

Classe di dimensioni Punto di interruzione Rappresentazione del dispositivo
Larghezza compatta width < 600dp 99,96% degli smartphone in verticale
Larghezza media 600 dp ≤ larghezza < 840 dp 93,73% dei tablet in verticale,

la maggior parte dei grandi display interni aperti in verticale

Larghezza espansa 840 dp ≤ larghezza < 1200 dp 97,22% dei tablet in orizzontale,

la maggior parte dei display interni aperti di grandi dimensioni in orizzontale ha almeno una larghezza espansa

Larghezza elevata 1200 dp ≤ larghezza < 1600 dp Display di tablet di grandi dimensioni
Larghezza extra large width ≥ 1600dp Display per computer
Altezza compatta altezza < 480 dp Il 99,78% degli smartphone in modalità orizzontale
Altezza media 480 dp ≤ altezza < 900 dp 96,56% dei tablet in orizzontale,

97,59% degli smartphone in verticale

Altezza espansa altezza ≥ 900 dp 94,25% dei tablet in verticale

Sebbene la visualizzazione delle classi di dimensioni come dispositivi fisici possa essere utile, le classi di dimensioni delle finestre non sono determinate esplicitamente dalle dimensioni dello schermo del dispositivo. Le classi di dimensioni della finestra non sono destinate alla logica di tipo isTablet. Le classi di dimensioni della finestra sono determinate dalle dimensioni della finestra disponibili per l'applicazione, indipendentemente dal tipo di dispositivo su cui viene eseguita l'app, il che ha due importanti implicazioni:

  • I dispositivi fisici non garantiscono una classe di dimensioni della finestra specifica. Lo spazio dello schermo disponibile per la tua app può differire dalle dimensioni dello schermo del dispositivo per molti motivi. Sui dispositivi mobili, la modalità schermo diviso può dividere lo schermo tra due applicazioni. Su ChromeOS, le app per Android possono essere presentate in finestre di tipo desktop ridimensionabili in modo arbitrario. I dispositivi pieghevoli possono avere due schermi di dimensioni diverse a cui si accede singolarmente piegando o aprendo il dispositivo.

  • La classe di dimensioni della finestra può cambiare durante il ciclo di vita dell'app. Mentre l'app è in esecuzione, le modifiche all'orientamento del dispositivo, il multitasking e l'apertura/chiusura possono modificare la quantità di spazio sullo schermo disponibile. Di conseguenza, la classe di dimensioni della finestra è dinamica e l'UI della tua app deve adattarsi di conseguenza.

Le classi di dimensioni della finestra corrispondono ai punti di interruzione compatti, medi ed espansi nelle linee guida per il layout di Material Design. Utilizza le classi di dimensioni delle finestre per prendere decisioni di alto livello sul layout dell'applicazione, ad esempio se utilizzare un layout canonico specifico per sfruttare lo spazio aggiuntivo dello schermo.

Puoi calcolare lo stato attuale WindowSizeClass utilizzando WindowSizeClass#compute() funzione fornita da Jetpack nella libreria WindowManager. Nell'esempio che segue mostra come calcolare la classe delle dimensioni della finestra e ricevere aggiornamenti ogni volta che modifiche alla classe delle dimensioni della finestra:

Kotlin

class MainActivity : Activity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        val container: ViewGroup = binding.container

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(object : View(this) {
            override fun onConfigurationChanged(newConfig: Configuration?) {
                super.onConfigurationChanged(newConfig)
                computeWindowSizeClasses()
            }
        })

        computeWindowSizeClasses()
    }

    private fun computeWindowSizeClasses() {
        val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this)
        val width = metrics.bounds.width()
        val height = metrics.bounds.height()
        val density = resources.displayMetrics.density
        val windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass
        // COMPACT, MEDIUM, or EXPANDED
        val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Java

public class MainActivity extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        // ...

        // Replace with a known container that you can safely add a
        // view to where the view won't affect the layout and the view
        // won't be replaced.
        ViewGroup container = binding.container;

        // Add a utility view to the container to hook into
        // View.onConfigurationChanged(). This is required for all
        // activities, even those that don't handle configuration
        // changes. You can't use Activity.onConfigurationChanged(),
        // since there are situations where that won't be called when
        // the configuration changes. View.onConfigurationChanged() is
        // called in those scenarios.
        container.addView(new View(this) {
            @Override
            protected void onConfigurationChanged(Configuration newConfig) {
                super.onConfigurationChanged(newConfig);
                computeWindowSizeClasses();
            }
        });

        computeWindowSizeClasses();
    }

    private void computeWindowSizeClasses() {
        WindowMetrics metrics = WindowMetricsCalculator.getOrCreate()
                .computeCurrentWindowMetrics(this);

        int width = metrics.getBounds().width
        int height = metrics.getBounds().height()
        float density = getResources().getDisplayMetrics().density;
        WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density)
        // COMPACT, MEDIUM, or EXPANDED
        WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass()
        // COMPACT, MEDIUM, or EXPANDED
        WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass()

        // Use widthWindowSizeClass and heightWindowSizeClass.
    }
}

Testare le classi di dimensioni della finestra

Man mano che apporti modifiche al layout, testa il comportamento del layout in tutte le dimensioni della finestra, soprattutto alle larghezze dei breakpoint compatti, medi ed espansi.

Se hai un layout esistente per schermi compatti, ottimizzalo prima per la classe di dimensioni della larghezza espansa, poiché questa classe di dimensioni offre lo spazio maggiore per contenuti aggiuntivi e modifiche all'interfaccia utente. Poi decidi quale layout è più adatto alla classe di dimensioni di larghezza media; valuta la possibilità di aggiungere un layout specializzato.

Passaggi successivi

Per scoprire di più su come utilizzare le classi di dimensioni delle finestre per creare layout reattivi/adattivi, consulta quanto segue:

Per scoprire di più su cosa rende un'app ideale per tutti i dispositivi e le dimensioni dello schermo, consulta: