Obsługa trybu wielu okien

Tryb wielookien umożliwia korzystanie z wielu aplikacji na tym samym ekranie. Aplikacje mogą być wyświetlane obok siebie lub jedna nad drugą (tryb podzielonego ekranu), jedna aplikacja w małym oknie nałożonym na inne aplikacje (tryb obrazu w obrazie) lub pojedyncze aplikacje w oddzielnych oknach, które można przenosić i zmieniać ich rozmiar (tryb okna na pulpicie).

Rysunek 1. Wyświetlanie 2 aplikacji obok siebie w trybie podzielonego ekranu.

Instrukcje dotyczące korzystania z trybu podzielonego ekranu na telefonach znajdziesz w artykule Wyświetlanie dwóch aplikacji jednocześnie na telefonie Pixel.

Funkcje wielu okien w poszczególnych wersjach

Sposób obsługi wielu okien zależy od wersji Androida i typu urządzenia:

  • Android 7.0 (poziom interfejsu API 24) wprowadził tryb podzielonego ekranu na urządzeniach z małym ekranem oraz tryb obrazu w obrazie na wybranych urządzeniach.

    • Tryb podzielonego ekranu wypełnia ekran 2 aplikacją, wyświetlając je obok siebie lub jedna nad drugą. Użytkownicy mogą przeciągać separator oddzielający 2 aplikacje, aby powiększyć jedną z nich i pomniejszyć drugą.

    • Tryb obraz w obrazie umożliwia użytkownikom kontynuowanie odtwarzania filmu podczas korzystania z innej aplikacji (patrz Obsługa obrazu w obrazie).

    • Tryb okna pulpitu, w którym użytkownicy mogą dowolnie zmieniać rozmiar każdej aktywności, może być włączony przez producentów urządzeń z dużym ekranem.

      Możesz skonfigurować sposób obsługi trybu wielookiennego przez aplikację, określając minimalne dopuszczalne wymiary aktywności. Możesz też wyłączyć tryb wielookienkowy dla aplikacji, ustawiając wartość resizeableActivity="false", aby mieć pewność, że system zawsze wyświetla aplikację na pełnym ekranie.

  • Android 8.0 (poziom interfejsu API 26) rozszerza tryb obrazu w obrazie na urządzenia z małym ekranem.

  • Android 12 (poziom 31 interfejsu API) czyni tryb wielookien standardowym.

    • Na dużych ekranach (średni lub rozszerzony rozmiar okna) platforma obsługuje wszystkie aplikacje w trybie wielookiennym niezależnie od ich konfiguracji. Jeśli resizeableActivity="false", aplikacja przechodzi w tryb zgodności, gdy zachodzi taka potrzeba, aby dostosować wymiary wyświetlacza.

    • Na małych ekranach (kompaktowych) system sprawdza minWidthminHeight, aby określić, czy aktywność może działać w trybie wielookiennym. Jeśli resizeableActivity="false", aplikacja nie może działać w trybie wielookiennym niezależnie od minimalnej szerokości i wysokości.

Tryb podzielonego ekranu

Użytkownicy aktywują tryb podzielonego ekranu w ten sposób:

  1. Otwórz ekran Ostatnie.
  2. Przesuń aplikację, aby ją wyświetlić
  3. Kliknij ikonę aplikacji na pasku tytułu aplikacji.
  4. Wybierz opcję menu podzielonego ekranu.
  5. wybrać inną aplikację na ekranie Ostatnie, albo zamknąć ekran Ostatnie i uruchomić inną aplikację;

Użytkownicy mogą zamknąć tryb podzielonego ekranu, przeciągając separator okna na krawędź ekranu w górę, w dół, w lewo lub w prawo.

Uruchom obok

Jeśli aplikacja potrzebuje dostępu do treści za pomocą intencji, możesz użyć FLAG_ACTIVITY_LAUNCH_ADJACENT, aby otworzyć treści w sąsiednim oknie podzielonego ekranu.

FLAG_ACTIVITY_LAUNCH_ADJACENT został wprowadzony w Androidzie 7.0 (poziom interfejsu API 24), aby umożliwić aplikacjom uruchomionym w trybie podzielonego ekranu uruchamianie działań w sąsiednim oknie.

W Androidzie 12L (poziom interfejsu API 32) i nowszych definicja flagi została rozszerzona, aby umożliwić aplikacjom działającym na pełnym ekranie aktywowanie trybu podzielonego ekranu, a następnie uruchamianie działań w sąsiednim oknie.

Aby uruchomić sąsiednią aktywność, użyj elementu FLAG_ACTIVITY_LAUNCH_ADJACENT w połączeniu z elementem FLAG_ACTIVITY_NEW_TASK, na przykład:

fun openUrlInAdjacentWindow(url:
String) { Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url)
addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or Intent.FLAG_ACTIVITY_NEW_TASK)
 }.also { intent -> startActivity(intent) } }

Cykl życia działania w trybie wielu okien

Tryb wielu okien nie zmienia cyklu życia aktywności. Stan wznowionych aplikacji w kilku oknach różni się jednak w zależności od wersji Androida.

Wielokrotne wznowienie

Android 10 (poziom interfejsu API 29) i nowsze wersje obsługują wielowątkowe wznawianie – wszystkie czynności pozostają w stanie RESUMED, gdy urządzenie jest w trybie wielozadaniowości. Aktywność może zostać wstrzymana, jeśli na jej wierzchu znajduje się inna, przezroczysta aktywność lub jeśli nie można jej wybrać, np. jest w trybie obrazu w obrazie. Możliwe też, że w danym momencie nie ma żadnej aktywnej czynności, na przykład gdy otwarta jest szuflada powiadomień. Metoda onStop() działa jak zwykle: jest wywoływana za każdym razem, gdy aktywność zostaje usunięta z ekranu.

Wielokrotne wznawianie jest też dostępne na wybranych urządzeniach z Androidem 9 (poziom interfejsu API 28). Aby włączyć obsługę wielu sesji na urządzeniach z Androidem 9, dodaj te metadane pliku manifestu:

<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />

Aby sprawdzić, czy dane metadane pliku manifestu są obsługiwane przez dane urządzenie, zapoznaj się ze specyfikacją urządzenia.

Android 9

W trybie wielookiennym w Androidzie 9 (interfejs API 28) i starszych tylko ostatnio używana aktywność jest aktywna w danym momencie. Ta aktywność jest uznawana za najwyższą i jest jedyną aktywnością w stanie RESUMED. Wszystkie inne widoczne działania są STARTED, ale nie RESUMED. Jednak system przyznaje tym widocznym, ale nie wznowionym aktywnościom wyższy priorytet niż aktywnościom, które nie są widoczne. Jeśli użytkownik wejdzie w interakcję z jednym z widocznych działań, to działanie zostanie wznowione, a poprzednio najwyższe działanie przejdzie w stan STARTED.

Jeśli w ramach jednego aktywnego procesu aplikacji występuje wiele aktywności, wznawiana jest aktywność o najwyższym porządku z-, a pozostałe są wstrzymywane.

Zmiany konfiguracji

Gdy użytkownik przełączy aplikację w tryb wielookienkowy, system powiadomi aktywność o zmianie konfiguracji zgodnie z opisem w sekcji Zarządzanie zmianami konfiguracji. Dzieje się tak też, gdy użytkownik zmieni rozmiar aplikacji lub przywróci tryb pełnoekranowy.

Ta zmiana ma zasadniczo takie same konsekwencje dla cyklu aktywności jak w przypadku, gdy system powiadamia aplikację, że urządzenie zmieniło orientację z pionowej na poziomą, z tym że wymiary aplikacji są zmieniane, a nie tylko zamieniane. Aktywność może sama obsłużyć zmianę konfiguracji lub aplikacja może zezwolić systemowi na zniszczenie aktywności i jej ponowne utworzenie z nowymi wymiarami.

Jeśli użytkownik zmienia rozmiar okna i zwiększa je w jednym z wymiarów, system dostosowuje rozmiar aktywności do działania użytkownika i w razie potrzeby wprowadzi zmiany konfiguracji. Jeśli aplikacja nie nadąża z rysowaniem nowo odsłoniętych obszarów, system tymczasowo wypełnia te obszary kolorem określonym przez atrybut windowBackground lub domyślny atrybut stylu windowBackgroundFallback.

Dostęp do zasobów specjalnych

Aby obsługiwać funkcję wznawiania z wielu miejsc, użyj wywołania zwrotnego cyklu życia onTopResumedActivityChanged().

Funkcja wywołania jest wywoływana, gdy aktywność zyska lub straci pozycję najwyższej wznawianej aktywności. Jest to ważne, gdy aktywność używa udostępnionego zasobu pojedynczego, takiego jak mikrofon lub kamera:

override fun
onTopResumedActivityChanged(topResumed: Boolean) { if (topResumed) { // Top
resumed activity. // Can be a signal to re-acquire exclusive resources. } else {
// No longer the top resumed activity. } }

Pamiętaj, że aplikacja może utracić zasoby z innych powodów, np. z powodu usunięcia wspólnego sprzętu.

W każdym przypadku aplikacja powinna prawidłowo obsługiwać zdarzenia i zmiany stanu, które wpływają na dostępne zasoby.

W przypadku aplikacji, które używają aparatu, CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() informuje, że może to być dobry moment na próbę uzyskania dostępu do aparatu. Ta metoda jest dostępna od Androida 10 (poziom interfejsu API 29).

Pamiętaj, że resizeableActivity=false nie gwarantuje wyłącznego dostępu do aparatu, ponieważ inne aplikacje korzystające z kamery mogą być otwierane na innych wyświetlaczach.

Rysunek 2. Aparat w trybie wielu okien.

Aplikacja nie musi zwalniać kamery, gdy traci ona ostrość. Możesz na przykład kontynuować podgląd aparatu, gdy użytkownik wchodzi w interakcję z nową aplikacją, która jest teraz na pierwszym planie. Aplikacja może nadal uruchamiać aparat, gdy nie jest to aplikacja na pierwszym planie, ale musi odpowiednio obsłużyć przypadek rozłączenia. Gdy aplikacja na pierwszym planie chce użyć aparatu, może go otworzyć, a Twoja aplikacja utraci do niego dostęp. Aplikacja może ponownie otworzyć aparat, gdy znów będzie on aktywny.

Gdy aplikacja otrzyma wywołanie zwrotne CameraDevice.StateCallback#onDisconnected(), kolejne wywołania na urządzeniu z aparatem będą wywoływać błąd CameraAccessException.

Wieloekranowe

Android 10 (poziom interfejsu API 29) obsługuje czynności na dodatkowych ekranach. Jeśli aktywność jest uruchamiana na urządzeniu z kilkoma wyświetlaczami, użytkownicy mogą przenosić ją z jednego wyświetlacza na inny. Wielokrotne wznawianie dotyczy również scenariuszy z wieloma ekranami; kilka aktywności może jednocześnie otrzymać dane wejściowe od użytkownika.

Aplikacja może określić, na którym wyświetlaczu ma się uruchamiać lub tworzyć kolejną aktywność. To zachowanie zależy od trybu uruchamiania aktywności zdefiniowanego w pliku manifestu oraz od flag i opcji intencji ustawionych przez podmiot uruchamiający aktywność. Więcej informacji znajdziesz w klasie ActivityOptions.

Gdy aktywność przejdzie na ekran dodatkowy, może zostać zaktualizowana pod kątem kontekstu, rozmiaru okna oraz konfiguracji i zmian zasobów. Jeśli aktywność obsługuje zmianę konfiguracji, o zmianie jest ona powiadamiana w onConfigurationChanged(); w przeciwnym razie aktywność jest ponownie uruchamiana.

Aktywność powinna sprawdzać bieżący widok w onCreate()onConfigurationChanged(), jeśli ma obsługiwać zmianę konfiguracji. Pamiętaj, aby aktualizować zasoby i schematy po zmianie wyświetlacza.

Jeśli wybrany tryb uruchamiania aktywności pozwala na uruchomienie wielu instancji, uruchomienie na drugim ekranie może utworzyć nową instancję aktywności. Obie aktywności są wznawiane jednocześnie.

Rysunek 3. Wiele wystąpień aktywności na wielu wyświetlaczach.

Warto też zapoznać się z interfejsami API wielu wyświetlaczy, które zostały wprowadzone w Androidzie 8.0.

Aktywność a kontekst aplikacji

W przypadku wyświetlaczy mniejszych znaczenie ma odpowiedni kontekst. Podczas uzyskiwania dostępu do zasobów kontekst aktywności (który jest wyświetlany) różni się od kontekstu aplikacji (który nie jest wyświetlany).

Kontekst aktywności zawiera informacje o wyświetlaczu i jest zawsze dostosowywany do obszaru wyświetlacza, w którym pojawia się aktywność. Dzięki temu możesz uzyskać prawidłowe informacje o gęstości wyświetlacza lub danych o oknie aplikacji. Aby uzyskać informacje o bieżącym oknie lub wyświetlaczu, zawsze używaj kontekstu aktywności (lub innego kontekstu opartego na interfejsie użytkownika). Ma to też wpływ na niektóre interfejsy systemowe, które używają informacji z kontekstu (patrz na przykład omówienie powiadomień toastowych).

Konfiguracja okna aktywności i wyświetlanie na poziomie nadrzędnym definiują zasoby i kontekst. Aby uzyskać bieżący wyświetlacz:

val activityDisplay = activity.getDisplay()

Dane o bieżącym oknie aktywności:

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Dane dotyczące maksymalnego okna dla bieżącej konfiguracji systemu:

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Dane z okresu maksymalnego służą do wykonywania obliczeń, wyboru układu lub określenia rozmiaru zasobów do pobrania z wyprzedzeniem. Dzięki temu w onCreate() możesz podejmować decyzje przed pierwszym przejściem przez układ. Nie należy ich używać do rozmieszczania konkretnych elementów widoku. Zamiast tego należy używać informacji z obiektu Configuration.

Wycięcia w ekranie

Składane urządzenia mogą mieć inną geometrię wycięcia w sposobie złożonym i rozłożonym. Aby uniknąć problemów z wycięciami, zapoznaj się z artykułem Obsługa wycięć na ekranie.

Wyświetlacze dodatkowe

Dostępne wyświetlacze możesz uzyskać z usługi systemowej DisplayManager:

val displayManager =
getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays =
displayManager.getDisplays()

Aby uzyskać informacje o konkretnym wyświetlaczu, takie jak rozmiar wyświetlacza lub flagi wskazujące, czy wyświetlacz jest bezpieczny, użyj klasy Display. Nie zakładaj jednak, że rozmiar wyświetlania będzie taki sam jak obszar wyświetlania przypisany do aplikacji. Pamiętaj, że w trybie wielu okien aplikacja zajmuje część ekranu.

Określ, czy aktywność może być uruchamiana na wyświetlaczu:

val activityManager =
getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val
activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context,
displayId, intent)

Następnie uruchom aktywność na wyświetlaczu:

val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent,
options.toBundle())

Obsługa kilku wyświetlaczy

Android obsługuje wyświetlanie na wielu ekranach klawiatur, tapet i launcherów.

Klawiatura programowa

Klawiatura może być wyświetlana na ekranie dodatkowym, jeśli jest skonfigurowana tak, aby obsługiwać ozdoby. Edytor metody wprowadzania tekstu automatycznie pojawia się, gdy pole tekstowe wymaga wpisania danych na wyświetlaczu.

Rysunek 4. Klawiatura na ekranie dodatkowym.

Tapeta

W Androidzie 10 (poziom interfejsu API 29) ekrany dodatkowe mogą mieć tapetę. Framework tworzy osobny egzemplarz WallpaperService.Engine dla każdego wyświetlacza. Upewnij się, że powierzchnia każdego silnika jest rysowana niezależnie. Deweloperzy mogą wczytywać komponenty za pomocą kontekstu wyświetlania w WallpaperService.Engine#getDisplayContext(). Sprawdź też, czy plik WallpaperInfo.xml zawiera ustawienia android:supportsMultipleDisplays="true".

Rysunek 5. Tapeta na telefonie i dodatkowym ekranie.

Launchery

Nowa kategoria filtra intencji SECONDARY_HOME zapewnia specjalną aktywność dla ekranów dodatkowych. Identyfikatory aktywności są używane na wszystkich wyświetlaczach, które obsługują ozdoby systemu, po jednym na każde wyświetlacze.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

Aktywność musi mieć tryb uruchamiania, który nie uniemożliwia uruchamiania wielu instancji i może się dostosować do różnych rozmiarów ekranu. Tryb uruchamiania nie może być singleInstance ani singleTask.

Na przykład implementacja AOSP Launcher3 obsługuje aktywność SECONDARY_HOME.

Rysunek 6. Aplikacja w stylu Material Design na telefonie
Rysunek 7. Launcher Material Design na dodatkowym ekranie.

Dane o okresie

W Androidzie 11 (poziom interfejsu API 30) wprowadzono następujące metody WindowManager, aby określać granice aplikacji działających w trybie wielu okien:

Metody biblioteki Jetpack WindowManager computeCurrentWindowMetrics() i computeMaximumWindowMetrics() oferują podobne funkcje, ale ze zgodnością wsteczną z poziomem interfejsu API 14.

Aby uzyskać dane o wyświetlaczach innych niż bieżący, wykonaj te czynności (jak pokazano w fragmentie kodu):

  • Tworzenie kontekstu displayowego
  • Tworzenie kontekstu okna dla wyświetlenia
  • Pobieranie WindowManager okna kontekstu
  • Pobierz WindowMetrics maksymalnej powierzchni wyświetlania dostępnej dla aplikacji

val windowMetrics =
context.createDisplayContext(display)
.createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
.getSystemService(WindowManager::class.java) .maximumWindowMetrics

Wycofane metody

W wersji 30 interfejsu API metody Display getSize()getMetrics() zostały wycofane na rzecz nowych metod WindowManager.

Android 12 (poziom API 31) wycofuje metody Display getRealSize()getRealMetrics() oraz aktualizuje ich działanie, aby było bardziej zbliżone do działania metody getMaximumWindowMetrics().

Konfiguracja trybu wielu okien

Jeśli Twoja aplikacja jest kierowana na Androida 7.0 (poziom interfejsu API 24) lub nowszego, możesz skonfigurować, w jaki sposób i czy aktywności w aplikacji obsługują tryb wielookienności. Możesz ustawić atrybuty w pliku manifestu, aby kontrolować rozmiar i układ. Ustawienia atrybutów aktywności głównej są stosowane do wszystkich aktywności w jej stosie zadań. Jeśli na przykład aktywność główna ma android:resizeableActivity="true", wszystkie aktywności w grupie zadań można zmieniać. Na niektórych większych urządzeniach, takich jak Chromebooki, aplikacja może działać w oknie, którego rozmiar można zmieniać, nawet jeśli określisz parametr android:resizeableActivity="false". Jeśli to spowoduje nieprawidłowe działanie aplikacji, możesz użyć filtrów w Google Play, aby ograniczyć dostępność aplikacji na takich urządzeniach.

Android 12 (poziom API 31) domyślnie używa trybu wielu okien. Na dużych ekranach (średni lub rozwinięty rozmiar okna) wszystkie aplikacje działają w trybie wielookiennym niezależnie od ich konfiguracji. Na małych ekranach system sprawdza ustawienia minWidth, minHeightresizeableActivity aktywności, aby określić, czy może ona działać w trybie wielookiennym.

resizeableActivity

Ustaw ten atrybut w elementach <activity> lub <application> pliku manifestu, aby włączyć lub wyłączyć tryb wielookienności dla poziomu interfejsu API 30 lub niższego:

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />;

Jeśli ten atrybut ma wartość true, aktywność może być uruchamiana w trybie podzielonego ekranu i trybie okna na pulpicie. Jeśli atrybut ma wartość false, aktywność nie obsługuje trybu wielookienkowego. Jeśli wartość to „false” (fałsz), a użytkownik spróbuje uruchomić działanie w trybie wielookiennym, działanie zajmie cały ekran.

Jeśli Twoja aplikacja jest kierowana na poziom interfejsu API 24 lub wyższy, ale nie określisz wartości tego atrybutu, jego wartość domyślna to „true”.

Jeśli Twoja aplikacja jest kierowana na poziom interfejsu API 31 lub nowszy, ten atrybut działa inaczej na małych i dużych ekranach:

  • Duże ekrany (średnia lub rozszerzona klasa rozmiaru okna): wszystkie aplikacje obsługują tryb wielu okien. Atrybut wskazuje, czy rozmiar aktywności można zmienić. Jeśli resizeableActivity="false", aplikacja przechodzi w tryb zgodności, gdy jest to konieczne, aby dostosować wymiary wyświetlacza.
  • Małe ekrany (klasa rozmiaru okna kompaktowego): jeśli resizeableActivity="true" oraz minimalna szerokość i minimalna wysokość aktywności spełniają wymagania dotyczące trybu wielookiennego, aktywność obsługuje tryb wielookienny. Jeśli resizeableActivity="false", aktywność nie obsługuje trybu wielookiennego niezależnie od minimalnej szerokości i wysokości aktywności.

supportsPictureInPicture

Aby wskazać, czy aktywność obsługuje tryb obrazu w obrazie, ustaw ten atrybut w węźle <activity> w pliku manifestu.

<activity
  android:name=".MyActivity"
  android:supportsPictureInPicture=["true" | "false"] />

configChanges

Aby samodzielnie obsługiwać zmiany konfiguracji w wielu oknach, np. gdy użytkownik zmienia rozmiar okna, dodaj atrybut android:configChanges do węzła manifestu <activity> aplikacji z co najmniej tymi wartościami:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize
      | screenLayout | orientation" />

Po dodaniu android:configChanges Twoja aktywność i jej fragmenty otrzymują wywołanie onConfigurationChanged(), zamiast być niszczone i ponownie tworzone. Następnie możesz ręcznie aktualizować widoki, ponownie wczytywać zasoby i wykonywać inne operacje w razie potrzeby.

<layout>

W Androidzie 7.0 (poziom interfejsu API 24) i nowszych element pliku manifestu <layout> obsługuje kilka atrybutów, które wpływają na sposób działania aktywności w trybie wielookiennym:

  • android:defaultHeight, android:defaultWidth: domyślna wysokość i szerokość aktywności po uruchomieniu w trybie okna na komputerze.

  • android:gravity: początkowe umieszczenie aktywności po uruchomieniu w trybie okna na komputerze. Odpowiednie wartości znajdziesz w klasie Gravity.

  • android:minHeight, android:minWidth: minimalna wysokość i minimalna szerokość dla aktywności zarówno w trybie podzielonego ekranu, jak i w trybie okna na komputerze. Jeśli użytkownik przesunie separator w trybie podzielonego ekranu, aby zmniejszyć aktywność do mniejszej niż określona minimalna wartość, system przytnie aktywność do rozmiaru określonego przez użytkownika.

Poniższy kod pokazuje, jak określić domyślny rozmiar i położenie aktywności oraz jej minimalny rozmiar, gdy jest wyświetlana w trybie okna na komputerze:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end|..."
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

Tryb wielu okien w czasie działania

Od Androida 7.0 system oferuje funkcje obsługujące aplikacje, które mogą działać w trybie wielozadaniowym.

Wyłączone funkcje w trybie wielu okien

W trybie wielookiennym Android może wyłączyć lub zignorować funkcje, które nie mają zastosowania do aktywności, która dzieli ekran urządzenia z innymi aktywnościami lub aplikacjami.

Dodatkowo niektóre opcje dostosowywania interfejsu użytkownika są wyłączone. Na przykład aplikacje nie mogą ukrywać paska stanu, jeśli działają w trybie wielookiennym (patrz Kontrolowanie widoczności interfejsu systemu).

System ignoruje zmiany atrybutu android:screenOrientation.

Zapytania i wywołania zwrotne w trybie wielu okien

Klasa Activity udostępnia te metody obsługi trybu wielookienkowego:

  • isInMultiWindowMode(): wskazuje, czy aktywność jest w trybie wielookiennym.

  • isInPictureInPictureMode(): wskazuje, czy aktywność jest w trybie obrazu w obrazie.

  • onMultiWindowModeChanged(): system wywołuje tę metodę, gdy aktywność przechodzi do trybu wielookiennego lub z niego wychodzi. System przekazuje metodzie wartość true, jeśli aktywność przechodzi w tryb wielu okien, lub false, jeśli aktywność opuszcza tryb wielu okien.

  • onPictureInPictureModeChanged(): system wywołuje tę metodę, gdy aktywność przechodzi w tryb obraz w obrazie lub z niego wychodzi. System przekazuje metodzie wartość true, jeśli aktywność wchodzi w tryb obrazu w obrazie, lub false, jeśli aktywność opuszcza tryb obrazu w obrazie.

Klasa Fragment udostępnia wersje wielu z tych metod, na przykład Fragment.onMultiWindowModeChanged().

Tryb obrazu w obrazie

Aby umieścić aktywność w trybie obrazu w obrazie, wywołaj metodę enterPictureInPictureMode(). Ta metoda nie ma żadnego wpływu, jeśli urządzenie nie obsługuje trybu obrazu w obrazie. Więcej informacji znajdziesz w artykule Dodawanie filmów za pomocą obrazu w obrazie (PiP).

Nowe czynności w trybie wielu okien

Podczas uruchamiania nowej aktywności możesz wskazać, że ma ona być wyświetlana obok bieżącej (jeśli to możliwe). Użyj flagi intencji FLAG_ACTIVITY_LAUNCH_ADJACENT, która informuje system, że ma spróbować utworzyć nową aktywność w sąsiednim oknie, aby obie aktywności były widoczne na ekranie. System dokłada wszelkich starań, aby to zrobić, ale nie jest to gwarantowane.

Jeśli urządzenie jest w trybie okna pulpitu i uruchamiasz nową aktywność, możesz określić wymiary nowej aktywności i jej położenie na ekranie, wywołując funkcję ActivityOptions.setLaunchBounds(). Metoda nie działa, jeśli urządzenie nie jest w trybie wielookiennym.

W interfejsie API 30 lub niższym, jeśli uruchomisz aktywność w grupie zadań, ta aktywność zastąpi aktywność na ekranie, dziedzicząc wszystkie właściwości dotyczące wielu okien. Jeśli chcesz uruchomić nową aktywność w nowym oknie w trybie wielookiennym, musisz ją uruchomić w nowym stosie zadań.

Android 12 (poziom API 31) umożliwia aplikacjom dzielenie okna aplikacji na wiele działań. Możesz określić, jak aplikacja ma wyświetlać aktywności – w trybie pełnoekranowym, obok siebie lub w kolonie – tworząc plik konfiguracji XML lub wykonując wywołania interfejsu Jetpack WindowManager API.

Przeciągnij i upuść

Użytkownicy mogą przeciągać i upuszczać dane z jednego zdarzenia do drugiego, gdy oba te zdarzenia są widoczne na ekranie. (przed Androidem 7.0 użytkownicy mogli przeciągać i upuszczać dane tylko w ramach jednej czynności). Aby szybko dodać obsługę przyjmowania treści z systemu plików, użyj interfejsu API DropHelper. Szczegółowe informacje o przeciąganiu i upuszczaniu znajdziesz w artykule Włączanie przeciągania i upuszczania.

Wiele instancji

Każda czynność główna ma własne zadanie, które działa w ramach osobnego procesu i jest wyświetlane w osobnym oknie. Aby uruchomić nową instancję aplikacji w oddzielnym oknie, możesz rozpocząć nowe aktywności za pomocą flagi FLAG_ACTIVITY_NEW_TASK. Możesz połączyć to z niektórymi atrybutami dotyczącymi wielu okien, aby zażądać określonej lokalizacji dla nowego okna. Aplikacja zakupowa może na przykład wyświetlać kilka okien, aby umożliwić porównywanie produktów.

Android 12 (poziom interfejsu API 31) umożliwia uruchamianie 2 wystąpieni aktywności obok siebie w tym samym oknie zadania.

Jeśli chcesz, aby użytkownicy mogli uruchamiać kolejną instancję aplikacji z poziomu launchera lub paska aplikacji, sprawdź, czy w launcherze ustawione są wartości android:resizeableActivity="true" i czy nie używasz trybu uruchamiania, który uniemożliwia uruchamianie wielu instancji. Na przykład aktywność singleInstancePerTask może być instancjonowana wielokrotnie w różnych zadaniach, gdy ustawiona jest wartość FLAG_ACTIVITY_MULTIPLE_TASK lub FLAG_ACTIVITY_NEW_DOCUMENT.

Nie myl wielu wystąpień z układem wielopanelowym, np. prezentacją listy i szczegółów, która korzysta z SlidingPaneLayout i działa w ramach jednego okna.

Pamiętaj, że jeśli na składanym urządzeniu działa kilka instancji w osobnych oknach, po zmianie położenia urządzenia co najmniej jedna z nich może zostać przeniesiona na drugi plan. Załóżmy na przykład, że urządzenie jest rozłożone i ma 2 instancje aplikacji działające w 2 oknach po obu stronach zawiasu. Jeśli urządzenie jest złożone, jedno z nich może zostać zamknięte zamiast próby dopasowania okien obu instancji na mniejszym ekranie.

Weryfikacja w trybie wielu okien

Niezależnie od tego, czy Twoja aplikacja jest kierowana na interfejs API na poziomie 24 lub wyższym, sprawdź, jak zachowuje się w trybie wielozadaniowym, gdy użytkownik spróbuje uruchomić ją w tym trybie na urządzeniu z Androidem 7.0 lub nowszym.

Urządzenia testowe

Tryb wielookienkowy jest obsługiwany na urządzeniach z Androidem w wersji 7.0 (interfejs API na poziomie 24) lub nowszej.

Poziom interfejsu API 23 lub niższy

Gdy użytkownicy próbują użyć aplikacji w trybie wielu okien, system wymusza zmianę jej rozmiaru, chyba że aplikacja deklaruje stałą orientację.

Jeśli aplikacja nie deklaruje stałej orientacji, otwórz ją na urządzeniu z Androidem 7.0 lub nowszym i spróbuj uruchomić ją w trybie podzielonego ekranu. Sprawdź, czy użytkownik ma wystarczającą ilość miejsca na korzystanie z aplikacji po przymusowym zmianie jej rozmiaru.

Jeśli aplikacja ma ustaloną orientację, spróbuj uruchomić ją w trybie wielookiennym. Sprawdź, czy aplikacja pozostaje w trybie pełnoekranowym.

Poziomy interfejsu API od 24 do 30

Jeśli Twoja aplikacja jest kierowana na poziomy interfejsu API 24–30 i nie wyłącza obsługi wielu okien, sprawdź, czy w trybie okna podzielonego ekranu i trybie okna na komputerze występują te zachowania:

  • Uruchom aplikację na pełnym ekranie, a potem przełącz do trybu wielookiennego, naciskając i przytrzymując przycisk Ostatnie. Sprawdź, czy aplikacja przełącza się prawidłowo.

  • Uruchom aplikację bezpośrednio w trybie wielookiennym i sprawdź, czy uruchamia się prawidłowo. Aplikację możesz uruchomić w trybie wielu okien, naciskając przycisk Ostatnie, a następnie przytrzymując pasek tytułu aplikacji i przeciągając go do jednego z wyróżnionych obszarów na ekranie.

  • Zmień rozmiar aplikacji w trybie podzielonego ekranu, przeciągając linię podziału. Sprawdź, czy aplikacja zmienia rozmiar bez zawieszania się i czy niezbędne elementy interfejsu są widoczne.

  • Jeśli masz określone minimalne wymiary aplikacji, spróbuj zmienić rozmiar aplikacji tak, aby jej okno było mniejsze niż te wymiary. Sprawdź, czy nie można zmienić rozmiaru aplikacji na mniejszy niż określone minimalne wymiary.

  • Podczas wszystkich testów sprawdź, czy wydajność aplikacji jest akceptowalna. Na przykład sprawdź, czy nie ma zbyt długiego opóźnienia w aktualizowaniu interfejsu po zmianie rozmiaru aplikacji.

Poziom API 31 lub wyższy

Jeśli Twoja aplikacja jest kierowana na poziom interfejsu API 31 lub wyższy, a minimalna szerokość i minimalna wysokość głównej czynności są mniejsze lub równe odpowiednim wymiarom dostępnej powierzchni wyświetlacza, sprawdź wszystkie zachowania wymienione w sekcji Poziomy interfejsu API 24–30.

Lista kontrolna testów

Aby sprawdzić wydajność aplikacji w trybie wielookiennym, wykonaj te operacje. Te operacje należy wykonać zarówno w trybie podzielonego ekranu, jak i w trybie okna, chyba że zaznaczono inaczej.

  • Włączanie i wyłączanie trybu wielu okien

  • Przełącz się z aplikacji na inną aplikację i sprawdź, czy aplikacja zachowuje się prawidłowo, gdy jest widoczna, ale nieaktywna. Jeśli na przykład aplikacja odtwarza film, sprawdź, czy odtwarzanie filmu nie zostaje przerwane, gdy użytkownik wchodzi w interakcję z inną aplikacją.

  • W trybie podzielonego ekranu spróbuj przesunąć linię podziału, aby powiększyć lub zmniejszyć aplikację. Wypróbuj te operacje w ustawieniach obok siebie i jeden nad drugim. Sprawdź, czy aplikacja nie ulega awarii, czy widoczne są najważniejsze funkcje i czy zmiana rozmiaru nie trwa zbyt długo.

  • Wykonywanie kilku operacji zmiany rozmiaru w krótkim odstępie czasu. Sprawdź, czy aplikacja nie ulega awarii ani nie ma wycieku pamięci. Profil narzędzia Android Studio Memory Profiler zawiera informacje o wykorzystaniu pamięci przez aplikację (patrz Sprawdzanie wykorzystania pamięci przez aplikację za pomocą narzędzia Memory Profiler).

  • Używaj aplikacji w normalny sposób w różnych konfiguracjach okien i sprawdzaj, czy działa ona prawidłowo. Sprawdź, czy tekst jest czytelny, a elementy interfejsu użytkownika nie są za małe, aby można było z nimi wchodzić w interakcję.

Obsługa wielu okien wyłączona

Jeśli na poziomie interfejsu API 24–30 wyłączysz obsługę wielu okien za pomocą ustawienia android:resizeableActivity="false", uruchom aplikację na urządzeniu z Androidem 7.0–11 i spróbuj uruchomić ją w trybie podzielonego ekranu lub okna pulpitu. Sprawdź, czy aplikacja pozostaje w trybie pełnoekranowym.

Dodatkowe materiały

Więcej informacji o obsługiwaniu wielu okien na Androidzie:

Polecane dla Ciebie * Uwaga: tekst linku jest wyświetlany, gdy JavaScript jest wyłączony * Tryb zgodności urządzenia * Obsługa zmiany rozmiaru na dużym ekranie * Obsługa zmian konfiguracji