Classi di finestra

Le classi di dimensioni delle finestre sono un insieme di punti di interruzione dell'area visibile con i comandi vocali che ti consentono di progettare, sviluppare e testare layout adattabili/adattivi. 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 o espansa. La larghezza e l'altezza disponibili sono classificate separatamente, quindi in qualsiasi momento la tua app prevede due classi di dimensioni delle finestre: una per la larghezza e una per l'altezza. In genere, la larghezza disponibile è più importante dell'altezza disponibile a causa dell'ubiquità dello scorrimento verticale, pertanto la classe delle dimensioni della finestra della larghezza è probabilmente più pertinente all'UI della tua app.

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

Come mostrati nelle figure, i punti di interruzione consentono di continuare a pensare ai layout in termini di dispositivi e configurazioni. Ogni punto di interruzione della classe di dimensione rappresenta un caso tipico degli scenari tipici dei dispositivi, il che può essere un utile quadro di riferimento per la progettazione dei layout basati sui punti di interruzione.

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

più grandi display interni aperti in verticale

Larghezza espansa larghezza ≥ 840 dp il 97,22% dei tablet in orizzontale,

più grandi display interni aperti in orizzontale

Altezza compatta Altezza < 480 dp 99,78% degli smartphone in orizzontale
Altezza media 480 dp ≤ altezza < 900 dp il 96,56% dei tablet in orizzontale,

97,59% degli smartphone in verticale

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

Sebbene possa essere utile visualizzare le classi di dimensioni come dispositivi fisici, le classi di dimensioni delle finestre non sono esplicitamente determinate dalle dimensioni dello schermo del dispositivo. Le classi di dimensioni delle finestre non sono destinate alla logica di tipo isTablet. Piuttosto, le classi di dimensioni delle finestre sono determinate dalle dimensioni delle finestre 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 specifica classe di dimensioni delle finestre. Per diversi motivi, lo spazio disponibile sullo schermo dell'app può essere diverso dalle dimensioni dello schermo del dispositivo. Sui dispositivi mobili, la modalità schermo diviso può suddividere lo schermo tra due applicazioni. Su ChromeOS, le app Android possono essere presentate in finestre in formato libero ridimensionabili in modo arbitrario. I dispositivi pieghevoli possono avere due schermi di diverse dimensioni, accessibili singolarmente piegando o aprendo.

  • La classe delle dimensioni della finestra può cambiare durante l'intero ciclo di vita dell'app. Mentre l'app è in esecuzione, l'orientamento del dispositivo cambia, il multitasking e la quantità di spazio pieghevole e aperta può cambiare la quantità di spazio disponibile sullo schermo. Di conseguenza, la classe delle dimensioni della finestra è dinamica e l'UI della tua app dovrebbe adattarsi di conseguenza.

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

Puoi calcolare l'attuale WindowSizeClass utilizzando la funzione WindowSizeClass#compute() fornita dalla libreria Jetpack WindowManager. L'esempio seguente mostra come calcolare la classe di dimensioni della finestra e ricevere aggiornamenti ogni volta che la classe di dimensioni della finestra cambia:

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.
    }
}

Classi di dimensioni delle finestre di test

Man mano che apporti modifiche al layout, verificane il comportamento in tutte le dimensioni delle finestre, soprattutto in base alle larghezze dei punti di interruzione compatte, medie ed espanse.

Se già esiste un layout per gli schermi compatti, ottimizzalo per la classe di dimensioni della larghezza espansa, poiché questa classe di dimensioni offre la maggiore quantità di spazio per ulteriori modifiche a contenuti e UI. Decidi quindi quale layout è più adatto per la classe di larghezza media; valuta la possibilità di aggiungerne uno specializzato.

Passaggi successivi

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

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