Limitare l'orientamento delle app su smartphone e schermi esterni pieghevoli, ma non su display più grandi

La tua app funziona perfettamente sui telefoni in orientamento verticale, quindi l'hai limitata solo a questo orientamento. Tuttavia, vedi l'opportunità di fare di più sugli schermi grandi in orientamento orizzontale o sui pieghevoli aperti.

Come puoi fare entrambe le cose: limitare l'app all'orientamento verticale sullo schermo esterno di un pieghevole, ma abilitare l'orientamento orizzontale sullo schermo interno?

Questa guida è una misura temporanea finché non potrai migliorare la tua app per fornire il supporto completo per tutte le configurazioni dei dispositivi.

Risultati

L'app rimane in orientamento verticale sugli schermi piccoli, indipendentemente dalla rotazione del dispositivo. Sugli schermi grandi, l'app supporta gli orientamenti orizzontale e verticale.

Compatibilità con le versioni

Questa implementazione è compatibile con tutti i livelli API.

Dipendenze

Kotlin

implementation("androidx.window:window:1.5.1")
implementation("androidx.window:window-core:1.5.1")

Alla moda

implementation "androidx.window:window:1.5.1"
implementation "androidx.window:window-core:1.5.1"

Gestire l'orientamento dell'app

Per attivare l'orientamento orizzontale sugli schermi grandi, imposta il file manifest dell'app in modo che gestisca le modifiche dell'orientamento per impostazione predefinita. In fase di runtime, determina le dimensioni della finestra dell'app. Se la finestra dell'app è piccola, limita l'orientamento dell'app sostituendo l'impostazione dell'orientamento del file manifest.

1. Specificare l'impostazione dell'orientamento nel file manifest dell'app

Puoi evitare di dichiarare l'elemento screenOrientation del file manifest dell'app (in questo caso l'orientamento è impostato su unspecified per impostazione predefinita) o impostare l'orientamento dello schermo su fullUser. Se l'utente non ha bloccato la rotazione basata sul sensore, la tua app supporterà tutti gli orientamenti del dispositivo.

<activity
    android:name=".MyActivity"
    android:screenOrientation="fullUser">

La differenza tra unspecified e fullUser è sottile, ma importante. Se non dichiari un valore screenOrientation, il sistema sceglie l'orientamento e la policy utilizzata dal sistema per definire l'orientamento potrebbe variare da dispositivo a dispositivo.

D'altra parte, la specifica di fullUser corrisponde più da vicino al comportamento definito dall'utente per il dispositivo: se l'utente ha bloccato la rotazione basata sul sensore, l'app segue la preferenza dell'utente; in caso contrario, il sistema consente uno dei quattro orientamenti dello schermo possibili (verticale, orizzontale, verticale inverso o orizzontale inverso).

Inoltre, puoi utilizzare nosensor per determinare l'orientamento senza tenere conto dei dati del sensore, ma il seguente codice funzionerà allo stesso modo. Consulta screenOrientation.

2. Determinare le dimensioni dello schermo

Con il file manifest impostato per supportare tutti gli orientamenti consentiti dall'utente, puoi specificare l'orientamento dell'app a livello di programmazione in base alle dimensioni dello schermo.

Aggiungi le librerie Jetpack WindowManager al file build.gradle o build.gradle.kts del modulo:

Kotlin

implementation("androidx.window:window:version")
implementation("androidx.window:window-core:version")

Alla moda

implementation 'androidx.window:window:version'
implementation 'androidx.window:window-core:version'

Utilizza il metodo di Jetpack WindowManager WindowMetricsCalculator#computeMaximumWindowMetrics() per ottenere le dimensioni dello schermo del dispositivo come oggetto WindowMetrics. Le metriche della finestra possono essere confrontate con le classi di dimensioni della finestra per decidere quando limitare l'orientamento.

Le classi di dimensioni della finestra forniscono i punti di interruzione tra schermi piccoli e grandi schermi.

Utilizza i WindowSizeClass#minWidthDp e WindowSizeClass#minHeightDp punti di interruzione per determinare le dimensioni dello schermo:

/** Determines whether the device has a compact screen. **/
fun compactScreen() : Boolean {
    val metrics = WindowMetricsCalculator.getOrCreate().computeMaximumWindowMetrics(this)
    val width = metrics.bounds.width()
    val height = metrics.bounds.height()
    val density = resources.displayMetrics.density
    val windowSizeClass =
        BREAKPOINTS_V1.computeWindowSizeClass(width / density, height / density)
    return windowSizeClass.minWidthDp == 0
}
    Nota:
  • Gli esempi vengono implementati come metodi di un'attività; pertanto, l'attività viene dereferenziata come this nell'argomento di computeMaximumWindowMetrics().
  • Il metodo computeMaximumWindowMetrics() viene utilizzato al posto di computeCurrentWindowMetrics() perché l'app può essere avviata in modalità multi-finestra, che ignora l'impostazione dell'orientamento dello schermo. Non ha senso determinare le dimensioni della finestra dell'app e sostituire l'impostazione dell'orientamento a meno che la finestra dell'app non sia l'intero schermo del dispositivo.

Consulta WindowManager per istruzioni sulla dichiarazione delle dipendenze per rendere disponibile il computeMaximumWindowMetrics() metodo nella tua app.

3. Sostituire l'impostazione del file manifest dell'app

Dopo aver stabilito che il dispositivo ha dimensioni dello schermo compatte, puoi chiamare Activity#setRequestedOrientation() per sostituire l'impostazione del file manifest: screenOrientation

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    requestedOrientation = if (compactScreen())
        ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
        ActivityInfo.SCREEN_ORIENTATION_FULL_USER
    ...
    // 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)
            requestedOrientation = if (compactScreen())
                ActivityInfo.SCREEN_ORIENTATION_PORTRAIT else
                ActivityInfo.SCREEN_ORIENTATION_FULL_USER
        }
    })
}

Aggiungendo la logica ai metodi onCreate() e View.onConfigurationChanged(), puoi ottenere le metriche massime della finestra e sostituire l'impostazione dell'orientamento ogni volta che l'attività viene ridimensionata o spostata tra i display, ad esempio dopo una rotazione del dispositivo o quando un dispositivo pieghevole viene piegato o aperto. Per ulteriori informazioni su quando si verificano le modifiche alla configurazione e quando causano la ricreazione dell'attività, consulta Gestire le modifiche alla configurazione.

Se utilizzi Jetpack Compose, puoi utilizzare la stessa funzione compactScreen() nel Composable principale dell'app per ottenere lo stesso risultato.

Punti chiave

  • screenOrientation: impostazione del file manifest dell'app che consente di specificare il modo in cui l'app risponde alle modifiche dell'orientamento del dispositivo
  • Jetpack WindowManager: insieme di librerie che consentono di determinare le dimensioni e le proporzioni della finestra dell'app; compatibile con le versioni precedenti fino al livello API 14
  • Activity#setRequestedOrientation(): metodo con cui puoi modificare l'orientamento dell'app in fase di runtime

Raccolte che contengono questa guida

Questa guida fa parte di queste raccolte di guide rapide curate che riguardano obiettivi di sviluppo Android più ampi:

Consenti alla tua app di supportare un'esperienza utente ottimizzata su tablet, pieghevoli e dispositivi ChromeOS.

Hai domande o feedback?

Visita la nostra pagina delle domande frequenti e scopri le guide rapide oppure contattaci e comunicaci la tua opinione.