Składane urządzenia zapewniają wyjątkowe wrażenia podczas oglądania. Tryb tylnego wyświetlacza i tryb podwójnego ekranu umożliwiają tworzenie specjalnych funkcji wyświetlacza na urządzeniach składanych, takich jak podgląd selfie z tylnego aparatu oraz wyświetlanie kilku różnych wyświetlaczy na ekranach wewnętrznym i zewnętrznym.
Tryb tylnego wyświetlacza
Zazwyczaj, gdy urządzenie składane jest rozłożone, aktywny jest tylko ekran wewnętrzny. Tryb tylnego wyświetlacza pozwala przenieść aktywność na ekran zewnętrzny urządzenia składanego, który podczas rozłożenia urządzenia zwykle jest skierowany w stronę użytkownika. Wewnętrzny ekran wyłączy się automatycznie.
Nowatorską aplikacją jest wyświetlanie podglądu aparatu na ekranie zewnętrznym, dzięki czemu użytkownicy mogą robić selfie tylnym aparatem, który zwykle pozwala robić lepsze zdjęcia.
Aby włączyć tryb tylnego wyświetlacza, użytkownicy muszą odpowiedzieć w oknie z prośbą o zgodę na przełączanie ekranu, na przykład:
![](https://developer.android.com/static/images/guide/topics/large-screens/foldables/rear-display-dialog.png?authuser=9&hl=pl)
Okno tworzy system, więc nie musisz niczego programować. W zależności od stanu urządzenia wyświetlane są różne okna. Na przykład system każe użytkownikom otworzyć urządzenie, gdy jest zamknięte. Nie możesz dostosować tego okna, ale może się ono różnić w zależności od urządzenia od różnych dostawców OEM.
Tryb tylnego wyświetlacza możesz wypróbować w aplikacji aparatu Pixel Fold. Zobacz przykładową implementację w ćwiczeniu z programowania na stronie Korzystanie z aparatu.
Tryb Dual Screen
Tryb 2 ekranów umożliwia wyświetlanie treści na obu wyświetlaczach urządzenia składanego jednocześnie. Tryb 2 ekranu jest dostępny na Pixelu Fold z Androidem 14 (poziom interfejsu API 34) lub nowszym.
Przykładem może być korzystanie z funkcji tłumaczenia rozmowy na dwóch ekranach.
![](https://developer.android.com/static/images/guide/topics/large-screens/foldables/dual-screen-interpreter.png?authuser=9&hl=pl)
Automatyczne włączanie trybów
Dostęp do trybu tylnego wyświetlacza i trybu podwójnego ekranu możesz uzyskać za pomocą interfejsów API Jetpack WindowManager, począwszy od biblioteki w wersji 1.2.0-beta03.
Dodaj zależność WindowManager do pliku build.gradle
modułu aplikacji:
Odlotowe
dependencies { implementation "androidx.window:window:1.2.0-beta03" }
Kotlin
dependencies { implementation("androidx.window:window:1.2.0-beta03") }
Punkt wejścia to WindowAreaController
, który dostarcza informacje i zachowania związane z przenoszeniem okien między wyświetlaczami lub między obszarami wyświetlania na urządzeniu.
WindowAreaController
umożliwia tworzenie zapytań dotyczących listy dostępnych obiektów WindowAreaInfo
.
Użyj WindowAreaInfo
, by uzyskać dostęp do WindowAreaSession
– interfejsu reprezentującego funkcję aktywnego obszaru okien.
Aby określić dostępność konkretnego elementu WindowAreaCapability
, użyj właściwości WindowAreaSession
.
Każda możliwość jest powiązana z konkretnym elementem WindowAreaCapability.Operation
.
W wersjach 1.2.0-beta03 Jetpack WindowManager obsługuje dwa rodzaje operacji:
WindowAreaCapability.Operation.OPERATION_PRESENT_ON_AREA
– służy do uruchamiania trybu Dual ScreenWindowAreaCapability.Operation.OPERATION_TRANSFER_ACTIVITY_TO_AREA
– służy do włączania trybu tylnego wyświetlacza.
Oto przykład deklaracji zmiennych dla trybu tylnego wyświetlacza i trybu Dual Screen w głównej aktywności aplikacji:
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;
Oto jak zainicjować zmienne w metodzie onCreate()
w Twojej aktywności:
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; } } });
Zanim rozpoczniesz operację, sprawdź dostępność konkretnej funkcji:
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 currently available to be enabled. } WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE -> { // The selected display mode is currently available to 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 currently available to be enabled. } else if (capabilityStatus.equals(WindowAreaCapability.Status.WINDOW_AREA_STATUS_AVAILABLE)) { // The selected display mode is currently available to 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. }
Tryb Dual Screen
Ten przykład zamyka sesję, jeśli funkcja jest już aktywna lub wywołuje funkcję 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); } }
Zwróć uwagę na to, że WindowAreaPresentationSessionCallback
jest wykorzystywane w głównej aktywności w aplikacji.
Interfejs API wykorzystuje metodę detektora: gdy wysyłasz żądanie wyświetlenia treści na drugim wyświetlaczu urządzenia składanego, inicjujesz sesję, która jest zwracana za pomocą metody onSessionStarted()
detektora.
Gdy zamkniesz sesję, w metodzie onSessionEnded()
pojawi się potwierdzenie.
Aby utworzyć odbiornik, zaimplementuj interfejs WindowAreaPresentationSessionCallback
:
Kotlin
class MainActivity : AppCompatActivity(), windowAreaPresentationSessionCallback
Java
public class MainActivity extends AppCompatActivity implements WindowAreaPresentationSessionCallback
Detektor musi wdrożyć metody onSessionStarted()
, onSessionEnded(),
i onContainerVisibilityChanged()
.
Metody wywołania zwrotnego powiadamiają o stanie sesji i umożliwiają odpowiednie zaktualizowanie aplikacji.
Wywołanie zwrotne onSessionStarted()
otrzymuje WindowAreaSessionPresenter
jako argument.
Ten argument to kontener umożliwiający dostęp do obszaru okna i pokazywanie jego zawartości.
Prezentacja może zostać automatycznie zamknięta przez system, gdy użytkownik opuści główne okno aplikacji. Prezentację można też zamknąć, wywołując metodę WindowAreaSessionPresenter#close()
.
W przypadku pozostałych wywołań zwrotnych dla uproszczenia wystarczy sprawdzić, czy w treści funkcji nie występują błędy, i zapisać stan:
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); }
Aby zachować spójność w całym ekosystemie, użyj oficjalnej ikony Dual Screen, aby wskazać użytkownikom, jak włączyć lub wyłączyć tryb Dual Screen.
Praktyczny przykład znajdziesz na stronie DualScreenActivity.kt.
Tryb tylnego wyświetlacza
Podobnie jak w przypadku trybu podwójnego ekranu poniższy przykład funkcji toggleRearDisplayMode()
zamyka sesję, jeśli jest już aktywna lub wywołuje funkcję 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); } }
W tym przypadku wyświetlana aktywność jest wykorzystywana jako WindowAreaSessionCallback,
, co jest prostsze do wdrożenia, ponieważ wywołanie zwrotne nie odbiera prezentacji, która umożliwia wyświetlenie treści w obszarze okna, ale zamiast tego przenosi całą aktywność do innego obszaru:
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}"); } }
Aby zachować spójność w całym ekosystemie, używaj oficjalnej ikony tylnego aparatu, aby wskazać użytkownikom, jak włączyć lub wyłączyć tryb tylnego wyświetlacza.
Dodatkowe materiały
- Ćwiczenie z programowania dotyczące korzystania z aparatu
- Podsumowanie pakietu
androidx.window.area
- Przykładowy kod Jetpack WindowManager:
Polecane dla Ciebie
- Uwaga: tekst linku wyświetla się, gdy JavaScript jest wyłączony
- Zoptymalizuj aplikację aparatu na urządzeniach składanych dzięki Jetpack WindowManager