Supporto di pieghe a tre ante e pieghevoli orizzontali

Un pieghevole orizzontale in posizione chiusa e completamente aperta accanto a un pieghevole a tre ante in posizione chiusa e completamente aperta.

Gli sviluppatori spesso incontrano difficoltà uniche quando creano applicazioni per dispositivi pieghevoli, in particolare per dispositivi come Samsung Trifold o il Pixel Fold originale, che si apre in formato orizzontale (rotation_0 = landscape). Gli errori degli sviluppatori includono:

  • Ipotesi errate sull'orientamento del dispositivo
  • Casi d'uso trascurati
  • Mancata ricalcolo o memorizzazione nella cache dei valori in caso di modifiche alla configurazione

I problemi specifici relativi al dispositivo includono:

  • Una mancata corrispondenza nell'orientamento naturale del dispositivo tra i display esterno e interno (ipotesi basate su rotation_0 = portrait), che causa il malfunzionamento delle app durante le operazioni di apertura e chiusura
  • Densità dello schermo diverse e gestione errata delle modifiche alla configurazione density
  • Problemi di anteprima della videocamera causati dalla dipendenza del sensore della videocamera dall'orientamento naturale

Per offrire un'esperienza utente di alta qualità sui dispositivi pieghevoli, concentrati sulle seguenti aree critiche:

  • Determina l'orientamento dell'app in base all'area dello schermo effettiva occupata dall'app, non all'orientamento fisico del dispositivo
  • Aggiorna le anteprime della videocamera per gestire correttamente l'orientamento del dispositivo e le proporzioni, evitare le anteprime laterali e impedire immagini allungate o ritagliate
  • Mantieni la continuità dell'app durante la chiusura o l'apertura del dispositivo conservando lo stato con ViewModel o approcci simili oppure gestendo manualmente le modifiche alla densità dello schermo e all'orientamento, in modo da evitare riavvii dell'app o perdita dello stato
  • Per le app che utilizzano sensori di movimento, regola il sistema di coordinate in modo che sia allineato all'orientamento attuale dello schermo ed evita ipotesi basate su rotation_0 = portrait, garantendo interazioni utente precise

Creare app adattive

Se la tua app è già adattiva e rispetta il livello ottimizzato (Livello 2) descritto nelle norme sulla qualità delle app adattive, dovrebbe funzionare correttamente sui dispositivi pieghevoli. In caso contrario, prima di ricontrollare i dettagli specifici dei dispositivi pieghevoli a tre schermi e orizzontali, esamina i seguenti concetti di base dello sviluppo adattivo di Android.

Layout adattivi

La tua UI deve gestire non solo le diverse dimensioni dello schermo, ma anche le modifiche in tempo reale delle proporzioni, ad esempio l'apertura e l'inserimento delle modalità multi-finestra o di visualizzazione a finestre del computer. Per ulteriori indicazioni su come:

  • Progettare e implementare layout adattivi
  • Regolare la navigazione principale dell'app in base alle dimensioni della finestra
  • Utilizzare le classi di dimensioni della finestra per adattare la UI dell'app
  • Semplificare l'implementazione dei layout canonici, ad esempio elenco-dettagli, utilizzando le API Jetpack
App in formato letterbox su un dispositivo pieghevole aperto e la stessa app a schermo intero con un layout adattivo su un altro dispositivo pieghevole aperto.
Figura 1. Differenza tra layout non adattivi (con letterbox) e adattivi.

Classi di dimensioni della finestra

I dispositivi pieghevoli, inclusi quelli orizzontali e a tre schermi, possono passare istantaneamente dalle classi di dimensioni della finestra compatte, medie ed espanse. La comprensione e l'implementazione di queste classi garantiscono che l'app mostri i componenti di navigazione e la densità dei contenuti corretti per lo stato attuale del dispositivo.

Rappresentazione di un'app su dispositivi dimensionati in base alle classi di dimensioni delle finestre compatte, medie ed espanse.
Figura 2. Classi di dimensioni della finestra.

L'esempio seguente utilizza la libreria adattiva Material 3 per determinare la quantità di spazio disponibile per l'app richiamando prima la currentWindowAdaptiveInfo() funzione e poi utilizzando i layout corrispondenti per le tre classi di dimensioni della finestra:

val adaptiveInfo = currentWindowAdaptiveInfo()
val windowSizeClass = adaptiveInfo.windowSizeClass

when {
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Expanded
  windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
  else -> // Compact
}

Per ulteriori informazioni, consulta Utilizzare le classi di dimensioni della finestra.

Qualità delle app adattive

Il rispetto del Livello 2 (Ottimizzato per l'adattamento) o del Livello 1 (Adattamento differenziato) delle norme sulla qualità delle app adattive garantisce che la tua app offra un'esperienza utente coinvolgente sui dispositivi a tre schermi, sui dispositivi pieghevoli orizzontali e su altri dispositivi con schermi grandi. Le norme riguardano controlli critici su più livelli per passare da un'esperienza adattiva a un'esperienza differenziata.

Android 16 e versioni successive

Per le app che hanno come target Android 16 (livello API 36) e versioni successive, il sistema ignora le limitazioni relative a orientamento, ridimensionabilità e proporzioni sui display con larghezza minima >= 600 dp. Le app riempiono l'intera finestra di visualizzazione, indipendentemente da proporzioni o dall'orientamento preferito dall'utente, e la modalità di compatibilità con letterbox non viene più utilizzata.

Considerazioni speciali

I dispositivi pieghevoli a tre schermi e orizzontali introducono comportamenti hardware unici che richiedono una gestione specifica, in particolare per quanto riguarda sensori, anteprima della videocamera e continuità della configurazione (mantenimento dello stato durante la chiusura, l'apertura o il ridimensionamento).

Anteprima della videocamera

Un problema comune sui dispositivi pieghevoli orizzontali o nei calcoli delle proporzioni (in scenari come multi-finestra, visualizzazione a finestre del computer o display collegati) si verifica quando l'anteprima della videocamera appare allungata, laterale, ritagliata o ruotata.

Ipotesi non corrispondenti

Questo problema si verifica spesso sui dispositivi con schermi grandi e pieghevoli perché le app possono presupporre relazioni fisse tra le funzionalità della fotocamera, come le proporzioni e l'orientamento del sensore, e le funzionalità del dispositivo, come l'orientamento del dispositivo e l'orientamento naturale.

I nuovi fattori di forma mettono in discussione questa ipotesi. Un dispositivo pieghevole può modificare le dimensioni di visualizzazione e le proporzioni senza che l'orientamento del dispositivo cambi. Ad esempio, l'apertura di un dispositivo modifica le proporzioni, ma se l'utente non ruota il dispositivo, l'orientamento rimane lo stesso. Se un'app presuppone che le proporzioni siano correlate all'orientamento del dispositivo, potrebbe ruotare o scalare in modo errato l'anteprima della videocamera. Lo stesso può accadere se un'app presuppone che l'orientamento del sensore della videocamera corrisponda all'orientamento verticale del dispositivo, il che non è sempre vero per i dispositivi pieghevoli orizzontali.

Soluzione 1: Jetpack CameraX (consigliata)

La soluzione più semplice e robusta è utilizzare la libreria Jetpack CameraX. Il relativo elemento UI PreviewView è progettato per gestire automaticamente tutte le complessità dell'anteprima:

  • PreviewView si adatta correttamente all'orientamento del sensore, alla rotazione del dispositivo e alla scalabilità.
  • Mantiene le proporzioni dell'immagine della videocamera, in genere centrando e ritagliando (FILL_CENTER).
  • Se necessario, puoi impostare il tipo di scala su FIT_CENTER per aggiungere letterbox all'anteprima.

Per ulteriori informazioni, consulta Implementare un'anteprima nella documentazione di CameraX.

Soluzione 2: CameraViewfinder

Se utilizzi una codebase Camera2 esistente, la libreria CameraViewfinder (compatibile con le versioni precedenti fino al livello API 21) è un'altra soluzione moderna. Semplifica la visualizzazione del feed videocamera utilizzando un TextureView o un SurfaceView e applicando tutte le trasformazioni necessarie (proporzioni, scala e rotazione).

Per ulteriori informazioni, consulta il post del blog Introducing Camera Viewfinder e Anteprima della videocamera la guida per gli sviluppatori.

Soluzione 3: implementazione manuale di Camera2

Se non puoi utilizzare CameraX o CameraViewfinder, devi calcolare manualmente l'orientamento e le proporzioni e assicurarti che i calcoli vengano aggiornati a ogni modifica della configurazione:

  • Ottieni l'orientamento del sensore della videocamera (ad esempio, 0, 90, 180, 270 gradi) da CameraCharacteristics.
  • Ottieni la rotazione attuale del display del dispositivo (ad esempio, 0, 90, 180, 270 gradi).
  • Utilizza questi due valori per determinare le trasformazioni necessarie per SurfaceView o TextureView.
  • Assicurati che le proporzioni di Surface di output corrispondano a quelle dell'anteprima della videocamera per evitare distorsioni.
  • L'app Fotocamera potrebbe essere in esecuzione in una parte dello schermo, in modalità multi-finestra o di visualizzazione a finestre del computer oppure su un display collegato. Per questo motivo, le dimensioni dello schermo non devono essere utilizzate per determinare le dimensioni del mirino della videocamera, ma devono essere utilizzate le metriche della finestra.

Per ulteriori informazioni, consulta la guida per gli sviluppatori Anteprima della videocamera e il video La tua app Fotocamera su diversi fattori di forma.

Soluzione 4: eseguire azioni di base della videocamera utilizzando un intent

Se non hai bisogno di molte funzionalità della videocamera, una soluzione semplice è eseguire azioni di base della videocamera, come scattare una foto o registrare un video, utilizzando l'applicazione Fotocamera predefinita del dispositivo. Non devi eseguire l'integrazione con una libreria della videocamera, ma utilizzare un intent.

Per ulteriori informazioni, consulta Intent della videocamera.

Configurazione e continuità

I dispositivi pieghevoli migliorano la versatilità della UI, ma possono avviare più modifiche alla configurazione rispetto ai dispositivi non pieghevoli. La tua app deve gestire queste modifiche alla configurazione e le relative combinazioni, ad esempio la rotazione del dispositivo, l'apertura/chiusura e il ridimensionamento della finestra in modalità multi-finestra o desktop, mantenendo o ripristinando lo stato dell'app. Ad esempio, le app devono mantenere la seguente continuità:

  • Stato dell'app senza arresti anomali o modifiche disruptive per gli utenti (ad esempio, quando si cambia schermo o si invia l'app in background)
  • Posizione di scorrimento dei campi scorrevoli
  • Testo digitato nei campi di testo e stato della tastiera
  • Posizione di riproduzione dei contenuti multimediali in modo che la riproduzione riprenda da dove era stata interrotta quando è stata avviata la modifica della configurazione

Le modifiche alla configurazione attivate di frequente includono screenSize, smallestScreenSize, screenLayout, orientation, density, fontScale, touchscreen e keyboard.

Consulta android:configChanges e Gestire le modifiche alla configurazione. Per ulteriori informazioni sulla gestione dello stato dell'app, consulta Salvare gli stati della UI.

Modifiche alla configurazione della densità

Gli schermi esterno e interno dei dispositivi pieghevoli a tre schermi e orizzontali potrebbero avere densità di pixel diverse. Pertanto, la gestione della modifica della configurazione per density richiede maggiore attenzione. In genere, Android riavvia l'attività quando la densità del display cambia, il che può causare la perdita di dati. Per impedire al sistema di riavviare l'attività, dichiara la gestione della densità nel file manifest e gestisci la modifica della configurazione in modo programmatico nella tua app.

Configurazione di AndroidManifest.xml

  • density: dichiara che l'app gestirà la modifica della densità dello schermo
  • Altre modifiche alla configurazione: è anche consigliabile dichiarare altre modifiche alla configurazione che si verificano di frequente, ad esempio screenSize, orientation, keyboardHidden, fontScale e così via

La dichiarazione della densità (e di altre modifiche alla configurazione) impedisce al sistema di riavviare l'attività e chiama invece onConfigurationChanged().

Implementazione di onConfigurationChanged()

Quando si verifica una modifica della densità, devi aggiornare le risorse (ad esempio ricaricare le bitmap o ricalcolare le dimensioni del layout) nel callback:

  • Verifica che il DPI sia stato modificato in newConfig.densityDpi
  • Reimposta le visualizzazioni personalizzate, gli elementi disegnabili personalizzati e così via sulla nuova densità

Elementi di risorse da elaborare

  • Risorsa immagine: sostituisci le bitmap e gli elementi disegnabili con risorse specifiche per la densità o regola direttamente la scala
  • Unità di layout (conversione da dp a px): ricalcola le dimensioni, il margine, il padding della visualizzazione
  • Dimensioni del carattere e del testo: riapplica le dimensioni del testo in unità sp
  • Disegno View/Canvas personalizzato: aggiorna i valori basati sui pixel utilizzati per disegnare Canvas

Determinare l'orientamento dell'app

Non fare mai affidamento sulla rotazione fisica del dispositivo quando crei app adattive, perché verrà ignorata sui dispositivi con schermi grandi e un'app in modalità multi-finestra potrebbe avere un orientamento diverso da quello del dispositivo. Utilizza invece Configuration.orientation o WindowMetrics per identificare se la tua app è attualmente in orientamento orizzontale o verticale in base alle dimensioni della finestra.

Soluzione 1: utilizzare Configuration.orientation

Questa proprietà identifica l'orientamento in cui viene attualmente visualizzata l'app.

Soluzione 2: utilizzare WindowMetrics#getBounds()

Puoi ottenere i limiti di visualizzazione attuali dell'app e controllare la larghezza e l'altezza per determinare l'orientamento.

Se devi limitare l'orientamento dell'app sugli smartphone (o sugli schermi esterni dei dispositivi pieghevoli), ma non sui dispositivi con schermi grandi, consulta Limitare l'orientamento dell'app sugli smartphone.

Posizioni e modalità di visualizzazione

Le posizioni e gli stati dei dispositivi pieghevoli, come la modalità da tavolo e HALF_OPENED sono supportati sia dai dispositivi pieghevoli verticali sia da quelli orizzontali. I dispositivi a tre schermi, tuttavia, non supportano la posizione da tavolo e non possono essere utilizzati HALF_OPENED. I dispositivi a tre schermi offrono invece uno schermo più grande per un'esperienza utente unica quando sono completamente aperti.

Per differenziare la tua app sui dispositivi pieghevoli che supportano HALF_OPENED, utilizza le API Jetpack WindowManager come FoldingFeature.

Scopri di più sulle posizioni, sugli stati e sul supporto dell'anteprima della videocamera dei dispositivi pieghevoli nelle seguenti guide per gli sviluppatori:

I dispositivi pieghevoli offrono esperienze di visualizzazione uniche. La modalità display posteriore e la modalità a doppio schermo ti consentono di creare funzionalità di visualizzazione speciali per i dispositivi pieghevoli, come l'anteprima dei selfie con la fotocamera posteriore e display simultanei ma diversi sugli schermi interno ed esterno. Per ulteriori informazioni, consulta:

Bloccare l'orientamento sull'orientamento naturale del sensore

Per casi d'uso molto specifici, in particolare per le app che devono occupare l'intero schermo indipendentemente dallo stato di chiusura del dispositivo, il flag nosensor ti consente di bloccare l'app sull'orientamento naturale del dispositivo. Ad esempio, su un Pixel Fold, l'orientamento naturale del dispositivo quando è chiuso è verticale, mentre l'orientamento naturale quando è aperto è orizzontale. L'aggiunta del flag nosensor forza l'app a essere bloccata in verticale quando è in esecuzione sul display esterno e in orizzontale quando è in esecuzione sul display interno.

<activity
  android:name=".MainActivity"
  android:screenOrientation="nosensor">

Rimappatura dei sensori di giochi e XR

Per i giochi e le app XR, i dati dei sensori non elaborati (come giroscopio o accelerometro) vengono forniti nel sistema di coordinate fisso del dispositivo. Se l'utente ruota il dispositivo per giocare in orizzontale, gli assi dei sensori non ruotano con lo schermo, il che comporta controlli di gioco errati.

Per risolvere il problema, controlla l'attuale Display.getRotation() e rimappa gli assi di conseguenza:

  • Rotazione 0: x=x, y=y
  • Rotazione 90: x=-y, y=x
  • Rotazione 180: x=-x, y=-y
  • Rotazione 270: x=y, y=-x

Per i vettori di rotazione (utilizzati nelle app bussola o XR), utilizza SensorManager.remapCoordinateSystem() per mappare la direzione dell'obiettivo della videocamera o la parte superiore dello schermo sui nuovi assi in base alla rotazione attuale.

Compatibilità con le app

Le applicazioni devono rispettare le norme sulla qualità delle app per garantire la compatibilità su tutti i fattori di forma e i display collegati. Se un'applicazione non è in grado di rispettare le norme, i produttori di dispositivi possono implementare trattamenti di compatibilità, anche se ciò potrebbe peggiorare l'esperienza utente.

Per ulteriori informazioni, consulta l'elenco completo delle soluzioni alternative di compatibilità fornite nella piattaforma, in particolare quelle relative all'anteprima della videocamera, alle sostituzioni e alle modifiche dell'API Android 16 che potrebbero modificare il comportamento dell'app.

Per scoprire di più sulla creazione di app adattive, consulta le norme sulla qualità delle app adattive.