Tryb wielookienkowy 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).
Instrukcje dotyczące korzystania z trybu podzielonego ekranu na telefonach znajdziesz w artykule Wyświetlanie dwóch aplikacji jednocześnie na telefonie Pixel.
Funkcje obsługi 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 aplikacji, 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 interakcji z inną aplikacją (patrz Obsługa funkcji obraz 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. Aby wyłączyć tryb wielu okien w swojej aplikacji, ustaw
resizeabableActivity="false"
, aby 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
minWidth
iminHeight
, aby określić, czy aktywność może działać w trybie wielookiennym. JeśliresizeableActivity="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:
- Otwórz ekran Ostatnie.
- Przesuń aplikację, aby ją wyświetlić
- Kliknij ikonę aplikacji na pasku tytułu aplikacji.
- Wybierz opcję menu podzielonego ekranu.
- Wybierz inną aplikację na ekranie Ostatnie lub zamknij ekran Ostatnie i uruchom 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 musi uzyskiwać dostęp do treści za pomocą intencji, możesz użyć polecenia FLAG_ACTIVITY_LAUNCH_ADJACENT
, aby otworzyć zawartość 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.
Android 12L (poziom interfejsu API 32) i nowsze rozszerzyli definicję flagi, aby aplikacje działające na pełnym ekranie mogły aktywować tryb podzielonego ekranu i uruchamiać działania 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:
Kotlin
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) } }
Java
public void openUrlInAdjacentWindow(String url) { Intent intent = new Intent(Intent.ACTION_VIEW); intent.setData(Uri.parse(url)); intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent); }
Cykl aktywności 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. Działanie może zostać wstrzymane, jeśli jest nad nim przezroczyste lub nie można go zaznaczyć, np. gdy działa ona 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 normalnie: jest wywoływana za każdym razem, gdy działanie zostanie usunięte z ekranu.
Wielokrotne wznawianie jest też dostępne na wybranych urządzeniach z Androidem 9 (poziom interfejsu API 28). Aby włączyć wznawianie na wielu urządzeniach na Androidzie 9, dodaj te metadane pliku manifestu:
<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />
Aby sprawdzić, czy dane urządzenie obsługuje te metadane pliku manifestu, 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 uważana za najwyższą i jest jedyną aktywnością w stanie RESUMED
. Wszystkie inne widoczne aktywności 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
.
Gdy w jednym aktywnym procesie aplikacji jest wiele działań, wznawiane są te o najwyższej kolejności na osi Z, a pozostałe – wstrzymane.
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 zmieni rozmiar okna i zwiększy je w jednym z wymiarów, system zmieni rozmiar aktywności, aby dopasować ją do działania użytkownika, i w razie potrzeby wprowadzać zmiany w 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ść staje się główną wznowioną aktywnością lub traci tę pozycję. Jest to ważne, gdy aktywność używa udostępnionego zasobu pojedynczego, takiego jak mikrofon lub kamera:
Kotlin
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. } }
Java
@Override public void onTopResumedActivityChanged(boolean topResumed) { 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 korzystają z aparatu, CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged()
wskazuje, że warto spróbować uzyskać do niego dostęp.
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.
Aplikacja nie musi zwalniać aparatu, gdy traci 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 najwyżej wznowiona aplikacja będzie chciała użyć aparatu, może go uruchomić, a aplikacja utraci do niego dostęp. Aplikacja może ponownie uruchomić aparat, gdy przywróci ostrość.
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 powinna się wyświetlać po uruchomieniu lub podczas tworzenia innej aktywności. 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, jest o niej powiadamiana (onConfigurationChanged()
). W przeciwnym razie jest ponownie uruchamiana.
Aktywność powinna sprawdzać bieżący widok w onCreate()
i onConfigurationChanged()
, jeśli obsługuje zmianę konfiguracji. Pamiętaj, aby aktualizować zasoby i schematy po zmianie wyświetlacza.
Jeśli wybrany tryb uruchamiania aktywności pozwala na uruchamianie wielu instancji, uruchomienie na ekranie dodatkowym może utworzyć nową instancję aktywności. Obie aktywności są wznawiane w tym samym momencie.
Warto też zapoznać się z interfejsami API wielu wyświetlaczy, które zostały wprowadzone w Androidzie 8.0.
Kontekst działania lub 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 uzyskasz prawidłowe informacje o gęstości wyświetlania lub wskaźnikach okien w aplikacji. Aby uzyskać informacje o bieżącym oknie lub wyświetlaczu, zawsze korzystaj z kontekstu działania (lub innego kontekstu interfejsu). 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 nadrzędne definiują zasoby i kontekst. Aby uzyskać bieżący wyświetlacz:
Kotlin
val activityDisplay = activity.getDisplay()
Java
Display activityDisplay = activity.getDisplay();
Dane o bieżącym oknie aktywności:
Kotlin
val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()
Java
WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();
Dane dotyczące maksymalnego okna dla bieżącej konfiguracji systemu:
Kotlin
val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()
Java
WindowMetrics 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
:
Kotlin
val displayManager = getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays = displayManager.getDisplays()
Java
DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE); Display[] 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 interfejsu będzie taki sam jak obszar wyświetlania przypisany do Twojej aplikacji. Pamiętaj, że w trybie wielu okien
aplikacja zajmuje część ekranu.
Określ, czy aktywność może być uruchamiana na wyświetlaczu:
Kotlin
val activityManager = getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent)
Java
ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);
Następnie uruchom aktywność na wyświetlaczu:
Kotlin
val options = ActivityOptions.makeBasic() options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent, options.toBundle())
Java
ActivityOptions 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 wyświetlacz jest skonfigurowany tak, aby obsługiwać ozdoby systemowe. Edytor metody wprowadzania tekstu automatycznie pojawia się, gdy pole tekstowe wymaga wpisania danych na wyświetlaczu.
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()
. Upewnij się też, że Twój plik WallpaperInfo.xml
ustawia android:supportsMultipleDisplays="true"
.
Launchery
Nowa kategoria filtra intencji, SECONDARY_HOME
, udostępnia dedykowane działanie dla ekranów dodatkowych. Przykłady aktywności są używane na wszystkich wyświetlaczach, które obsługują system dekoracji, po jednym na każdy wyświetlacz.
<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. Nie może to być tryb uruchamiania singleInstance
ani singleTask
.
Na przykład implementacja AOSP elementu Launcher3
obsługuje działanie SECONDARY_HOME
.
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:
getCurrentWindowMetrics()
: zwraca obiektWindowMetrics
odpowiadający bieżącemu stanowi okienk w systemie.getMaximumWindowMetrics()
: zwracaWindowMetrics
dla największego potencjalnego stanu okienkowego systemu.
Metody biblioteki Jetpack WindowManager computeCurrentWindowMetrics()
i computeMaximumWindowMetrics()
oferują podobne funkcje, ale ze zgodnością wsteczną z poziomem interfejsu API 14.
Aby uzyskać dane dotyczące wyświetlaczy innych niż bieżący, wykonaj te czynności (jak pokazano w fragmentie kodu):
- Tworzenie kontekstu displayowego
- Tworzenie kontekstu okna dla wyświetlenia
- Pobieranie
WindowManager
kontekstu okna - Wykorzystaj
WindowMetrics
maksymalnego obszaru wyświetlania dostępnego dla aplikacji.
Kotlin
val windowMetrics = context.createDisplayContext(display) .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null) .getSystemService(WindowManager::class.java) .maximumWindowMetrics
Java
WindowMetrics windowMetrics = context.createDisplayContext(display) .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null) .getSystemService(WindowManager.class) .getMaximumWindowMetrics();
Wycofane metody
Metody Display
getSize()
i getMetrics()
zostały wycofane w interfejsie API 30 i zastąpione nowymi metodami WindowManager
.
Android 12 (poziom API 31) wycofuje metody Display
getRealSize()
i 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 wielu okien. 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, np. na Chromebookach, aplikacja może działać w oknie z możliwością zmiany rozmiaru, nawet jeśli ustawisz 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 (klasa średniego lub rozwiniętego rozmiaru okna) wszystkie aplikacje działają w trybie wielu okien niezależnie od ich konfiguracji. Na małych ekranach system sprawdza ustawienia minWidth
, minHeight
i resizeableActivity
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 okna pulpitu. 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 zasada ma wartość
resizeableActivity="false"
, w razie potrzeby aplikacja jest przełączana w tryb zgodności, aby dostosować się do wymiarów wyświetlania. - 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 zasada ma wartośćresizeableActivity="false"
, aktywność nie obsługuje trybu wielu okien 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 klasieGravity
.android:minHeight
,android:minWidth
: minimalna wysokość i minimalna szerokość dla aktywności w trybie podzielonego ekranu i okna na pulpicie. 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
Począwszy od Androida 7.0 system oferuje funkcje obsługi aplikacji działających w trybie wielu okien.
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 w atrybucie 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ę za każdym razem, gdy aktywność przechodzi w tryb wielu okien 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 ustawić aktywność w trybie obrazu w obrazie, wywołaj enterPictureInPictureMode()
. Ta metoda nie działa, 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
Gdy uruchamiasz nowe działanie, możesz wskazać, że ma być wyświetlane obok bieżącego. Użyj flagi intencji FLAG_ACTIVITY_LAUNCH_ADJACENT
, która informuje system, że ma spróbować utworzyć nową aktywność w sąsiednim oknie, tak aby 2 działania korzystały z tego samego ekranu. Nasz system stara się, aby było to możliwe, 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 ramach grupy 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ść jako osobne okno w trybie wielu okien, 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 zadania do drugiego, gdy oba te zadania są widoczne na ekranie. Przed Androidem 7.0 użytkownicy mogli przeciągać
i upuszczać dane w ramach jednej czynności. Aby szybko dodać obsługę przyjmowania treści z pliku, 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 połączenie z niektórymi atrybutami dotyczącymi wielu okien, aby wskazać konkretną lokalizację 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 umożliwić użytkownikom uruchamianie innej instancji aplikacji z poziomu menu z aplikacjami lub paska zadań, upewnij się, że aktywność w programie uruchamiającym ma ustawioną wartość android:resizeableActivity="true"
i nie używasz trybu uruchamiania, który uniemożliwia wiele instancji. Na przykład, jeśli skonfigurowano FLAG_ACTIVITY_MULTIPLE_TASK
lub FLAG_ACTIVITY_NEW_DOCUMENT
, działanie singleInstancePerTask
może zostać utworzone wiele razy w ramach różnych zadań.
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 w wersji 7.0 lub nowszej.
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, uruchom ją na urządzeniu z Androidem 7.0 lub nowszym i spróbuj uruchomić ją w trybie podzielonego ekranu. Sprawdź, czy korzystanie z aplikacji jest akceptowalne w przypadku wymuszania zmiany rozmiaru aplikacji.
Jeśli aplikacja ma ustaloną orientację, spróbuj ustawić ją w trybie wielookiennym. Upewnij się, że aplikacja pozostaje wtedy w trybie pełnoekranowym.
Poziomy interfejsu API 24–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 się przełącza 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 rozmiar aplikacji zmienia się bez awarii 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 tak, aby jej rozmiar był 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.
Interfejs API na poziomie 31 lub wyższym
Jeśli Twoja aplikacja jest kierowana na interfejs API na poziomie 31 lub wyższym, a minimalna szerokość i minimalna wysokość głównego działania są mniejsze lub równe odpowiednim wymiarom dostępnego obszaru wyświetlania, sprawdź wszystkie działania wymienione dla poziomów interfejsu API od 24 do 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ą 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. Narzędzie do profilowania pamięci w Android Studio udostępnia informacje o wykorzystaniu pamięci przez aplikację (patrz Sprawdzanie wykorzystania pamięci przez aplikację za pomocą narzędzia Memory Profiler).
Używaj aplikacji normalnie 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 obsługa wielu okien została wyłączona na poziomach interfejsu API 24–30 za pomocą ustawienia android:resizeableActivity="false"
, uruchom aplikację na urządzeniu z Androidem w wersji od 7.0 do 11 i spróbuj włączyć w niej tryb podzielonego ekranu i okna na komputery. Sprawdź, czy aplikacja pozostaje w trybie pełnoekranowym.
Dodatkowe materiały
Więcej informacji o obsługiwaniu wielu okien na Androidzie:
- Przykład aplikacji MultiWindowPlayground na Androida
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