En matière d'affichage, les appareils pliables offrent des expériences uniques. Les modes d'affichage arrière et Dual Screen vous permettent de proposer des fonctionnalités spéciales pour les appareils pliables, comme l'aperçu de selfie avec la caméra arrière, mais aussi d'afficher simultanément des contenus distincts sur l'écran intérieur et extérieur.
Mode d'affichage arrière
En règle générale, lorsqu'un appareil pliable est en position dépliée, seul l'écran intérieur est actif. Le mode d'affichage arrière vous permet de déplacer une activité vers l'écran extérieur, qui n'est généralement pas orienté vers l'utilisateur lorsque l'appareil est déplié. L'écran intérieur s'éteint alors automatiquement.
Une nouvelle application consiste à afficher l'aperçu de l'appareil photo sur l'écran extérieur, les utilisateurs peuvent prendre des selfies avec la caméra arrière, qui offre généralement de prise de vue que la caméra avant.
Pour activer le mode d'affichage arrière, les utilisateurs répondent à une boîte de dialogue permettant à l'application de changer d'écran, par exemple :
Le système crée la boîte de dialogue. Aucun développement de votre part n'est donc requis. Différentes boîtes de dialogue s'affichent en fonction de l'état de l'appareil. par exemple, le système invite les utilisateurs à déplier l'appareil s'il est fermé. Personnalisation impossible dans la boîte de dialogue, et cela peut varier sur les appareils de différents OEM.
Vous pouvez essayer le mode d'affichage arrière avec l'application Appareil photo du Pixel Fold. Voir un exemple dans l'atelier de programmation Optimiser votre application d'appareil photo sur les appareils pliables avec Jetpack WindowManager
Mode Dual Screen
Le mode Dual Screen vous permet d'afficher du contenu sur les deux écrans d'un appareil pliable en même temps. Ce mode est disponible sur les Pixel Fold équipés d'Android 14 (niveau d'API 34) ou version ultérieure.
Par exemple, l'interprète Dual Screen est un exemple de cas d'utilisation.
Approche programmatique d'activation des modes
Vous pouvez accéder aux modes d'affichage arrière et Dual Screen via le Jetpack WindowManager, à partir de la version 1.2.0-beta03 de la bibliothèque.
Ajoutez la dépendance WindowManager au fichier build.gradle
du module de votre application :
Groovy
dependencies { implementation "androidx.window:window:1.2.0-beta03" }
Kotlin
dependencies { implementation("androidx.window:window:1.2.0-beta03") }
Le point d'entrée est l'élément WindowAreaController
, qui fournit les informations et le comportement liés au déplacement des fenêtres entre les écrans ou entre les zones d'affichage d'un appareil. WindowAreaController
vous permet d'interroger la liste des
objets WindowAreaInfo
disponibles.
Utilisez WindowAreaInfo
pour accéder à WindowAreaSession
, une interface qui représente une fonctionnalité de zone de fenêtre active. Utilisez WindowAreaSession
pour déterminer la disponibilité d'une WindowAreaCapability
spécifique.
Chaque capacité est liée à une WindowAreaCapability.Operation
particulier.
Dans la version 1.2.0-beta03, Jetpack WindowManager prend en charge deux types d'opérations :
WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
, qui permet de lancer le mode Dual Screen.WindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
, qui permet de lancer le mode d'affichage arrière
Voici un exemple de déclaration de variables pour le mode d'affichage arrière mode double écran dans l'activité principale de votre application:
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;
Voici comment initialiser les variables dans la méthode onCreate()
de votre
activité:
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; } } });
Avant de démarrer une opération, vérifiez la disponibilité de la capacité concernée :
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. }
Mode Dual Screen
L'exemple suivant ferme la session si la capacité est déjà active.
Sinon, appelle la fonction 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); } }
Notez l'utilisation de l'activité principale de l'application en tant que
l'argument WindowAreaPresentationSessionCallback
.
L'API utilise une approche d'écouteur : lorsque vous envoyez une requête pour afficher le contenu sur l'autre écran d'un appareil pliable, vous démarrez une session qui est renvoyée via la méthode onSessionStarted()
de l'écouteur. Lorsque vous fermez
vous obtenez une confirmation dans la méthode onSessionEnded()
.
Pour créer l'écouteur, implémentez l'interface WindowAreaPresentationSessionCallback
:
Kotlin
class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback
Java
public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback
L'écouteur doit implémenter les méthodes onSessionStarted()
, onSessionEnded(),
et onContainerVisibilityChanged()
. Les méthodes de rappel notifient
l'état de la session et vous permettre de mettre à jour l'application en conséquence.
Le rappel onSessionStarted()
reçoit WindowAreaSessionPresenter
comme argument. L'argument est le conteneur qui vous permet d'accéder à une zone de fenêtre
et afficher du contenu. Le système peut automatiquement ignorer la présentation lorsque l'utilisateur quitte la fenêtre principale de l'application. La présentation peut également être fermée en appelant WindowAreaSessionPresenter#close()
.
Pour les autres rappels, pour plus de simplicité, il vous suffit de vérifier dans le corps de la fonction les éventuelles erreurs et consignez l'état:
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); }
Pour assurer la cohérence au sein de l'écosystème, utilisez l'icône officielle du Dual Screen pour indiquer aux utilisateurs comment activer ou désactiver ce mode.
Pour un exemple fonctionnel, consultez DualScreenActivity.kt.
Mode d'affichage arrière
Comme dans l'exemple du mode Dual Screen, l'exemple suivant
La fonction toggleRearDisplayMode()
ferme la session si la capacité est
déjà actif, ou appelle la méthode 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); } }
Dans ce cas, l'activité affichée est utilisée en tant que WindowAreaSessionCallback
.
ce qui est plus simple à implémenter, car le rappel ne reçoit pas de présentateur
qui permet d'afficher du contenu dans une fenêtre, mais transfère à la place l'intégralité
l'activité dans une autre zone:
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}"); } }
Pour assurer la cohérence au sein de l'écosystème, utilisez la caméra arrière officielle pour indiquer aux utilisateurs comment activer ou désactiver le mode d'affichage arrière.
Ressources supplémentaires
- Atelier de programmation Optimiser votre application d'appareil photo sur les appareils pliables avec Jetpack WindowManager
- Résumé du package
androidx.window.area
- Exemple de code Jetpack WindowManager :