I dispositivi pieghevoli offrono esperienze di visualizzazione uniche. La modalità display posteriore e la modalità dual screen ti consentono di creare funzionalità di visualizzazione speciali per i dispositivi pieghevoli, come l'anteprima dei selfie con la fotocamera posteriore e i display simultanei, ma diversi, sugli schermi interno ed esterno.
Modalità di visualizzazione posteriore
In genere, quando un dispositivo pieghevole è aperto, è attivo solo lo schermo interno. La modalità di visualizzazione posteriore ti consente di spostare un'attività sullo schermo esterno di un dispositivo pieghevole, che di solito è rivolto verso l'esterno quando il dispositivo è aperto. La il display interno si spegne automaticamente.
Un'applicazione innovativa è la visualizzazione dell'anteprima della fotocamera sullo schermo esterno, in modo che gli utenti possano scattare selfie con la fotocamera posteriore, che in genere offre prestazioni molto migliori rispetto alla fotocamera anteriore.
Per attivare la modalità di visualizzazione posteriore, gli utenti rispondono a una finestra di dialogo per consentire all'app di cambiare schermata, ad esempio:

Il sistema crea la conversazione, quindi non è richiesta alcuna azione da parte tua. Vengono visualizzate finestre di dialogo diverse a seconda dello stato del dispositivo. ad esempio, il sistema indica agli utenti di aprire il dispositivo se quest'ultimo è chiuso. Non puoi personalizzare e può variare su dispositivi di OEM diversi.
Puoi provare la modalità di visualizzazione posteriore con l'app Fotocamera di Pixel Fold. Consulta un'implementazione di esempio nel codelab Ottimizzare l'app Fotocamera sui dispositivi pieghevoli con Jetpack WindowManager.
Modalità doppio schermo
La modalità Dual Screen ti consente di mostrare contemporaneamente i contenuti su entrambi i display di un dispositivo pieghevole. La modalità Dual Screen è disponibile su Pixel Fold con Android 14 (livello API 34) o versioni successive.
Un esempio di caso d'uso è l'interprete con doppio schermo.

Attivare le modalità in modo programmatico
Puoi accedere alla modalità display posteriore e doppio schermo tramite Jetpack API WindowManager, a partire dalla versione della libreria 1.2.0-beta03.
Aggiungi la dipendenza WindowManager al file build.gradle
del modulo dell'app:
Groovy
dependencies { implementation "androidx.window:window:1.2.0-beta03" }
Kotlin
dependencies { implementation("androidx.window:window:1.2.0-beta03") }
Il punto di contatto è WindowAreaController
, che fornisce informazioni e comportamenti relativi allo spostamento delle finestre tra i display o tra le aree di visualizzazione su un dispositivo. WindowAreaController
ti consente di eseguire query sull'elenco degli oggetti WindowAreaInfo
disponibili.
Usa WindowAreaInfo
per accedere a WindowAreaSession
, un'interfaccia che rappresenta una funzionalità dell'area della finestra attiva. Usa WindowAreaSession
per determinare
la disponibilità di uno specifico WindowAreaCapability
.
Ogni funzionalità è correlata a un determinato WindowAreaCapability.Operation
.
Nella versione 1.2.0-beta03, Jetpack WindowManager supporta due tipi di operazioni:
WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
, ovvero utilizzata per avviare la modalità Dual ScreenWindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
, che viene utilizzato per avviare la modalità di visualizzazione posteriore
Ecco un esempio di come dichiarare le variabili per la modalità display posteriore e modalità Dual Screen nell'attività principale dell'app:
Kotlin
private lateinit var windowAreaController: WindowAreaController private lateinit var displayExecutor: Executor private var windowAreaSession: WindowAreaSession? = null private var windowAreaInfo: WindowAreaInfo? = null private var capabilityStatus: WindowAreaCapability.Status = WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED private val dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA private val rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
Java
private WindowAreaControllerCallbackAdapter windowAreaController = null; private Executor displayExecutor = null; private WindowAreaSessionPresenter windowAreaSession = null; private WindowAreaInfo windowAreaInfo = null; private WindowAreaCapability.Status capabilityStatus = WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED; private WindowAreaCapability.Operation dualScreenOperation = WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA; private WindowAreaCapability.Operation rearDisplayOperation = WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA;
Ecco come inizializzare le variabili nel metodo onCreate()
del tuo
attività:
Kotlin
displayExecutor = ContextCompat.getMainExecutor(this) windowAreaController = WindowAreaController.getOrCreate() lifecycleScope.launch(Dispatchers.Main) { lifecycle.repeatOnLifecycle(Lifecycle.State.STARTED) { windowAreaController.windowAreaInfos .map { info -> info.firstOrNull { it.type == WindowAreaInfo.Type.TYPE_REAR_FACING } } .onEach { info -> windowAreaInfo = info } .map { it?.getCapability(operation)?.status ?: WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED } .distinctUntilChanged() .collect { capabilityStatus = it } } }
Java
displayExecutor = ContextCompat.getMainExecutor(this); windowAreaController = new WindowAreaControllerCallbackAdapter(WindowAreaController.getOrCreate()); windowAreaController.addWindowAreaInfoListListener(displayExecutor, this); windowAreaController.addWindowAreaInfoListListener(displayExecutor, windowAreaInfos -> { for(WindowAreaInfo newInfo : windowAreaInfos){ if(newInfo.getType().equals(WindowAreaInfo.Type.TYPE_REAR_FACING)){ windowAreaInfo = newInfo; capabilityStatus = newInfo.getCapability(presentOperation).getStatus(); break; } } });
Prima di avviare un'operazione, verifica la disponibilità del servizio delle funzionalità:
Kotlin
when (capabilityStatus) { WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED -> { // The selected display mode is not supported on this device. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE -> { // The selected display mode is not available. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> { // The selected display mode is available and can be enabled. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE -> { // The selected display mode is already active. } else -> { // The selected display mode status is unknown. } }
Java
if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNSUPPORTED)) { // The selected display mode is not supported on this device. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_UNAVAILABLE)) { // The selected display mode is not available. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) { // The selected display mode is available and can be enabled. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE)) { // The selected display mode is already active. } else { // The selected display mode status is unknown. }
Modalità doppio schermo
L'esempio seguente chiude la sessione se la funzionalità è già attiva oppure
altrimenti chiama la funzione presentContentOnWindowArea()
:
Kotlin
fun toggleDualScreenMode() { if (windowAreaSession != null) { windowAreaSession?.close() } else { windowAreaInfo?.token?.let { token -> windowAreaController.presentContentOnWindowArea( token = token, activity = this, executor = displayExecutor, windowAreaPresentationSessionCallback = this ) } } }
Java
private void toggleDualScreenMode() { if(windowAreaSession != null) { windowAreaSession.close(); } else { Binder token = windowAreaInfo.getToken(); windowAreaController.presentContentOnWindowArea( token, this, displayExecutor, this); } }
Nota che l'utilizzo dell'attività principale dell'app come
WindowAreaPresentationSessionCallback
.
L'API utilizza un approccio di ascolto: quando effettui una richiesta per presentare i contenuti
all'altro display di un dispositivo pieghevole, avvii una sessione che viene restituita
tramite il metodo onSessionStarted()
dell'ascoltatore. Quando chiudi la sessione, ricevi una conferma nel metodo onSessionEnded()
.
Per creare l'ascoltatore, implementa l'interfaccia WindowAreaPresentationSessionCallback
:
Kotlin
class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback
Java
public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback
L'ascoltatore deve implementare i metodi onSessionStarted()
, onSessionEnded(),
e onContainerVisibilityChanged()
. I metodi di callback ti informano sullo stato della sessione e ti consentono di aggiornare l'app di conseguenza.
Il callback onSessionStarted()
riceve un WindowAreaSessionPresenter
come
argomento. L'argomento è il container che ti consente di accedere all'area di una finestra
e mostrare i contenuti. La presentazione può essere ignorata automaticamente dal sistema
quando l'utente esce dalla finestra dell'applicazione principale oppure la presentazione può
chiuso chiamando WindowAreaSessionPresenter#close()
.
Per gli altri callback, per semplicità, controlla se nel corpo della funzione errori e registra lo stato:
Kotlin
override fun onSessionStarted(session: WindowAreaSessionPresenter) { windowAreaSession = session val view = TextView(session.context) view.text = "Hello world!" session.setContentView(view) } override fun onSessionEnded(t: Throwable?) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}") } } override fun onContainerVisibilityChanged(isVisible: Boolean) { Log.d(logTag, "onContainerVisibilityChanged. isVisible = $isVisible") }
Java
@Override public void onSessionStarted(@NonNull WindowAreaSessionPresenter session) { windowAreaSession = session; TextView view = new TextView(session.getContext()); view.setText("Hello world, from the other screen!"); session.setContentView(view); } @Override public void onSessionEnded(@Nullable Throwable t) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}"); } } @Override public void onContainerVisibilityChanged(boolean isVisible) { Log.d(logTag, "onContainerVisibilityChanged. isVisible = " + isVisible); }
Per mantenere la coerenza nell'intero ecosistema, utilizza l'icona ufficiale Dual Screen per indicare agli utenti come attivare o disattivare la modalità dual‑screen.
Per un esempio funzionante, consulta DualScreenActivity.kt.
Modalità di visualizzazione posteriore
Analogamente all'esempio della modalità Dual Screen, il seguente esempio di una
La funzione toggleRearDisplayMode()
chiude la sessione se la funzionalità è
già attivo, oppure chiama transferActivityToWindowArea()
:
Kotlin
fun toggleRearDisplayMode() { if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) { if(windowAreaSession == null) { windowAreaSession = windowAreaInfo?.getActiveSession( operation ) } windowAreaSession?.close() } else { windowAreaInfo?.token?.let { token -> windowAreaController.transferActivityToWindowArea( token = token, activity = this, executor = displayExecutor, windowAreaSessionCallback = this ) } } }
Java
void toggleDualScreenMode() { if(capabilityStatus == WindowAreaCapability.Status.WINDOW_AREA_STATUS_ACTIVE) { if(windowAreaSession == null) { windowAreaSession = windowAreaInfo.getActiveSession( operation ) } windowAreaSession.close() } else { Binder token = windowAreaInfo.getToken(); windowAreaController.transferActivityToWindowArea(token, this, displayExecutor, this); } }
In questo caso, l'attività visualizzata viene utilizzata come WindowAreaSessionCallback
,
che è più semplice da implementare perché il callback non riceve un presentatore
che consente di mostrare i contenuti in un'area della finestra, ma trasferisce l'intera
attività in un'altra area:
Kotlin
override fun onSessionStarted() { Log.d(logTag, "onSessionStarted") } override fun onSessionEnded(t: Throwable?) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}") } }
Java
@Override public void onSessionStarted(){ Log.d(logTag, "onSessionStarted"); } @Override public void onSessionEnded(@Nullable Throwable t) { if(t != null) { Log.e(logTag, "Something was broken: ${t.message}"); } }
Per mantenere la coerenza in tutto l'ecosistema, utilizza la fotocamera ufficiale della fotocamera posteriore. per indicare agli utenti come attivare o disattivare la modalità schermo posteriore.
Risorse aggiuntive
- Ottimizzare l'app Fotocamera sui dispositivi pieghevoli con Jetpack WindowManager codelab
- Riepilogo del pacchetto
androidx.window.area
- Codice di esempio di Jetpack WindowManager: