Obsługa trybu wielu okien

Tryb wielu okien umożliwia jednoczesne używanie tego samego ekranu przez wiele aplikacji. Aplikacje mogą znajdować się obok siebie lub jedna nad drugą (w trybie podzielonego ekranu), jedną w małym oknie nakładającą się na inne aplikacje (w trybie obraz w obrazie) lub pojedyncze aplikacje w osobnych ruchomych oknach z możliwością zmiany rozmiaru (tryb swobodny).

Rysunek 1. Wyświetl 2 aplikacje obok siebie w trybie podzielonego ekranu.

Wygoda użytkowników zależy od wersji systemu operacyjnego Android i typu urządzenia:

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

    W trybie podzielonego ekranu na ekranie pojawiają się 2 aplikacje, które wyświetlają się obok siebie lub jedna nad drugą. Użytkownicy mogą przeciągnąć linię podziału, aby powiększyć jedną aplikację, a drugą zmniejszyć.

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

    Producenci urządzeń z dużymi ekranami mogą włączyć tryb dowolnego formatu, w którym użytkownicy mogą dowolnie zmieniać rozmiar każdej aktywności.

    Aby skonfigurować obsługę trybu wielu okien przez aplikację, określ minimalne dopuszczalne wymiary aktywności. Możesz też wyłączyć w aplikacji tryb wielu okien, ustawiając resizeableActivity="false", aby system zawsze wyświetlał aplikację na pełnym ekranie.

  • Android 8.0 (poziom interfejsu API 26) udostępnia tryb obrazu w obrazie na urządzenia z małymi ekranami.
  • Android 12 (poziom interfejsu API 31) umożliwia standardowe działanie trybu wielu okien.

    W przypadku dużych ekranów (sw >= 600 dp) platforma obsługuje wszystkie aplikacje w trybie wielu okien niezależnie od ich konfiguracji. Jeśli resizeableActivity="false" jest potrzebny, aplikacja przechodzi w tryb zgodności, gdy jest to konieczne do obsługi wymiarów związanych z wyświetlaniem.

    Na małych ekranach (o parametrach < 600 dp) system sprawdza minWidth i minHeight aktywności, aby ustalić, czy może ona działać w trybie wielu okien. Jeśli resizeableActivity="false", aplikacja nie może działać w trybie wielu okien niezależnie od minimalnej szerokości i wysokości.

    Uwaga: producenci urządzeń mogą zastąpić te ustawienia.

Tryb podzielonego ekranu

Użytkownicy mogą włączyć tryb podzielonego ekranu, wykonując te czynności:

  1. Otwórz ekran Ostatnie.
  2. Przesuń aplikację, aby znalazła się na ekranie
  3. Kliknij ikonę aplikacji na pasku tytułu aplikacji.
  4. Wybierz opcję menu podzielonego ekranu
  5. Wybierz inną aplikację na ekranie Ostatnie lub zamknij ten ekran i uruchom inną aplikację

Użytkownicy mogą wyjść z trybu podzielonego ekranu, przeciągając separator w górę, w dół, w lewo lub w prawo.

Uruchom w sąsiedztwie

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.

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

W Androidzie 12L (poziom interfejsu API 32) i nowszych poszerzono 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ć powiązane działanie, użyj właściwości 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 życia aktywności w trybie wielu okien

Tryb wielu okien nie zmienia cyklu aktywności. Wznowienie działania aplikacji w wielu 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ą wiele wznawiania – wszystkie aktywności pozostają w stanie RESUMED, gdy urządzenie jest w trybie wielu okien. Aktywność można wstrzymać, jeśli jest nad nią przezroczysta aktywność lub nie można jej zaznaczyć, np. w trybie obraz w obrazie. Może się też zdarzyć, że żadna aktywność nie będzie w danym momencie koncentrowana, na przykład gdy otwarty jest panel powiadomień. Metoda onStop działa w zwykły sposób; jest wywoływana przy każdym usunięciu działania z ekranu.

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

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

Aby sprawdzić, czy dane urządzenie obsługuje te metadane manifestu, zapoznaj się ze specyfikacją urządzenia.

Android 9

W trybie wielu okien na Androidzie 9 (poziom interfejsu API 28) i starszych w danym momencie aktywna jest tylko aktywność, z którą użytkownik ostatnio wchodził w interakcję. To działanie jest uznawane za najwyższe i jest jedyną aktywnością w stanie RESUMED. Pozostałe widoczne aktywności to STARTED, ale nie RESUMED. System nadaje jednak tym widocznym, ale nie wznowionym aktywnościom, wyższy priorytet niż te, które nie są widoczne. Jeśli użytkownik wejdzie w interakcję z jedną z widocznych aktywności, zostanie ona wznowiona, a aktywność najwyższego poziomu przechodzi w stan STARTED.

Gdy w jednym aktywnym procesie aplikacji jest wiele działań, ta o najwyższej kolejności nakładanej jest wznawiana, a pozostałe – wstrzymywane.

Zmiany konfiguracji

Gdy użytkownik przełączy aplikację w tryb wielu okien, system powiadamia o zmianie konfiguracji zgodnie z opisem w sekcji Obsługa zmian konfiguracji. Dzieje się tak również wtedy, gdy użytkownik zmieni rozmiar aplikacji lub przełączy ją z powrotem w tryb pełnoekranowy.

Zasadniczo ta zmiana ma taki sam wpływ na cykl życia aktywności jak w sytuacji, gdy system powiadamia aplikację, że urządzenie zostało przełączone z pionowej na poziomą. Jedyna różnica jest taka, że po zmianie wymiarów urządzenie nie jest tylko zamieniane. Jak wspomnieliśmy w sekcji Obsługa zmian konfiguracji, aktywność może obsłużyć zmianę konfiguracji lub może pozwolić systemowi na jej zniszczenie i odtworzenie jej z nowymi wymiarami.

Jeśli użytkownik zmienia rozmiar okna i powiększa je w przypadku któregokolwiek z wymiarów, system zmienia rozmiar aktywności, aby dopasować ją do działania użytkownika i w razie potrzeby wprowadzić zmiany w konfiguracji. Jeśli aplikacja ma opóźnienie w rysowaniu nowych 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 wyjątkowych zasobów

Aby ułatwić obsługę funkcji wielokrotnego wznawiania, udostępniliśmy nowe wywołanie zwrotne cyklu życia: onTopResumedActivityChanged().

Ta metoda jest wywoływana, gdy aktywność zyska lub utraci najwyższą pozycję wznowionego działania. To ważne, jeśli chcesz wiedzieć, kiedy aktywność korzysta ze współdzielonego zasobu, np. mikrofonu lub kamery.

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, takich jak usunięcie udostępnionego sprzętu.

W każdym przypadku aplikacja powinna płynnie obsługiwać zdarzenia i zmiany stanu, które mają wpływ na dostępne zasoby.

W przypadku aplikacji korzystających z aparatu CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() sugeruje, ż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 aparatu można otwierać na innych ekranach.

Aparat w trybie wielu okien.

Rysunek 2. Aparat w trybie wielu okien.

Aplikacja nie musi zwalniać aparatu, gdy traci ostrość. Możesz na przykład kontynuować podgląd aparatu, gdy użytkownik będzie korzystać z najnowszej wznowionej aplikacji. Aplikacja może nadal uruchamiać kamerę, gdy nie jest to najczęściej wznawiana aplikacja, ale musi prawidłowo obsługiwać zgłoszenie odłączenia. Gdy najwyżej wznowiona aplikacja chce użyć aparatu, może ją otworzyć, a aplikacja utraci dostęp. Aplikacja może ponownie uruchomić aparat, gdy znów będzie na nim ostrość.

Gdy aplikacja odbierze wywołanie zwrotne CameraDevice.StateCallback#onDisconnected(), kolejne połączenia przychodzące na urządzenie kamery będą zwracały sygnał CameraAccessException.

Wieloekranowe

Android 10 (poziom interfejsu API 29) obsługuje działania na wyświetlaczach dodatkowych. Jeśli aktywność jest wykonywana na urządzeniu z kilkoma wyświetlaczami, użytkownicy mogą ją przenosić z jednego ekranu na drugi. Wielokrotne wznawianie można też stosować w scenariuszach obejmujących wiele urządzeń – do kilku działań w tym samym czasie mogą trafiać dane wejściowe użytkownika.

Aplikacja może określić, na którym wyświetlaczu ma się uruchomić, gdy uruchomi się lub utworzy inną aktywność. Działanie to zależy od trybu uruchamiania aktywności zdefiniowanego w pliku manifestu oraz od flag i opcji intencji ustawionych przez encję uruchamiającą działanie. Więcej informacji znajdziesz w sekcji ActivityOptions.

Gdy działanie zostanie przeniesione na wyświetlacz dodatkowy, może zostać poddane aktualizacji kontekstu, zmiany rozmiaru okien oraz zmian konfiguracji i zasobów. Jeśli aktywność obsługuje zmianę konfiguracji, jest o niej powiadamiana w narzędziu onConfigurationChanged(). W przeciwnym razie jest uruchamiana ponownie.

W przypadku zmiany konfiguracji aktywność powinna sprawdzać bieżący sposób wyświetlania w onCreate i onConfigurationChanged. Pamiętaj o zaktualizowaniu zasobów i układów po zmianie widoku.

Jeśli wybrany tryb uruchamiania aktywności pozwala na wiele wystąpień, uruchomienie na ekranie dodatkowym może spowodować utworzenie jej nowej instancji. Obie aktywności zostaną wznowione w tym samym czasie.

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

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

Możesz też poczytać o interfejsach API multi-display, które zostały wprowadzone w Androidzie 8.0.

Aktywność a kontekst aplikacji

W przypadku reklam na wielu ekranach korzystanie z odpowiedniego kontekstu ma kluczowe znaczenie. Podczas uzyskiwania dostępu do zasobów kontekst działania (wyświetlany) różni się od kontekstu aplikacji (który nie jest).

Kontekst aktywności zawiera informacje o wyświetlaniu i jest zawsze dostosowany do obszaru wyświetlania, w którym pojawia się aktywność. Dzięki temu uzyskasz prawidłowe informacje o gęstości wyświetlania lub wskaźnikach okien aplikacji. Aby uzyskać informacje o bieżącym oknie lub wyświetlaczu, zawsze korzystaj z kontekstu aktywności (lub innego kontekstu opartego na interfejsie). Dotyczy to też niektórych interfejsów API systemu, które korzystają z informacji pochodzących z kontekstu (np. komunikaty ogółem).

Konfiguracja okna aktywności i widok nadrzędny definiują zasoby i kontekst. Pobierz bieżący wyświetlacz w ten sposób:

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

Pobierz dane bieżącego okresu aktywności:

Kotlin

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

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

Pobierz maksymalne wskaźniki okien dla bieżącej konfiguracji systemu:

Kotlin

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

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

Maksymalne wskaźniki okien służą do przeprowadzania obliczeń, wyboru układu oraz określania z wyprzedzeniem rozmiaru zasobów do pobrania. Udostępnienie tej funkcji w onCreate() umożliwia podejmowanie decyzji przed pierwszym przekazaniem układu. Tych danych nie należy używać do wyznaczania konkretnych elementów widoku. Zamiast tego używaj informacji z obiektu Configuration.

Wycięcia w ekranie

Złożone i rozłożone urządzenia mogą mieć różne geometria wycięcia. Aby uniknąć problemów z wycięciem, przeczytaj artykuł o sprawdzonych metodach obsługi wycięcia w ekranie.

Wyświetlacze dodatkowe

Dostępne wyświetlacze możesz uzyskać w usłudze 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();

Użyj klasy Display, aby uzyskać informacje o danym wyświetlaczu, takie jak rozmiar wyświetlacza lub flagi wskazujące, czy wyświetlacz jest bezpieczny. Nie zakładaj jednak, że rozmiar wyświetlacza 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ć uruchomiona na ekranie:

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 ekranie:

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 umożliwia korzystanie z wielu ekranów w przypadku klawiatur programowych, tapet i programów uruchamiających.

Klawiatura programowa

Na ekranie dodatkowym można wyświetlić klawiaturę, jeśli wyświetlacz jest skonfigurowany do obsługi dekoracji systemowych. Edytor metody wprowadzania pojawi się automatycznie, gdy pole tekstowe będzie wymagało wprowadzenia danych na tym wyświetlaczu.

Klawiatura na dodatkowym ekranie.

Rysunek 4. Klawiatura na dodatkowym ekranie.

Tapety

W Androidzie 10 (poziom interfejsu API 29) ekrany dodatkowe mogą mieć tapetę. Platforma tworzy osobną instancję WallpaperService.Engine dla każdego wyświetlenia. Pamiętaj, że powierzchnia każdego silnika musi być narysowana niezależnie. Deweloperzy mogą wczytywać zasoby w narzędziu WallpaperService.Engine#getDisplayContext(), korzystając z kontekstu wyświetlania. Sprawdź też, czy Twoje zestawy plików WallpaperInfo.xml android:supportsMultipleDisplays="true".

Tapeta na telefonie i dodatkowym wyświetlaczu.

Rysunek 5. Tapeta na telefonie i dodatkowym wyświetlaczu.

Launchery

Nowa kategoria filtra intencji, SECONDARY_HOME, zapewnia dedykowane działanie na potrzeby ekranów dodatkowych. Wystąpienia aktywności są używane na wszystkich wyświetlaczach, które obsługują dekoracje systemu, 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 blokuje wielu wystąpień i dostosowuje się do różnych rozmiarów ekranu. Tryb uruchamiania nie może być trybem singleInstance ani singleTask.

Na przykład implementacja Launcher3 w AOSP obsługuje działanie SECONDARY_HOME.

Menu z aplikacjami Material Design na telefonie.

Rysunek 6. Menu z aplikacjami Material Design na telefonie.

Menu z aplikacjami w stylu Material Design na wyświetlaczu dodatkowym.

Rysunek 7. Menu z aplikacjami w stylu Material Design na wyświetlaczu dodatkowym.

Dane dotyczące okien

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

Metody biblioteki Jetpack WindowManagera computeCurrentWindowMetrics() i computeMaximumWindowMetrics() mają podobne funkcje, ale są zgodne wstecznie z interfejsem API na poziomie 14.

Aby uzyskać dane dla wyświetlaczy innych niż bieżący, wykonaj te czynności:

  • Tworzenie kontekstu wyświetlania
  • Utwórz kontekst okna dla wyświetlacza
  • 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 DisplaygetSize() i getMetrics() zostały wycofane na poziomie API 30 i zastąpione nowymi metodami WindowManager.

Android 12 (poziom interfejsu API 31) wycofuje metody Display getRealSize() i getRealMetrics() oraz aktualizuje ich działanie, aby lepiej dopasować je do działania getMaximumWindowMetrics().

Konfiguracja trybu wielu okien

Jeśli Twoja aplikacja jest kierowana na Androida 7.0 (poziom interfejsu API 24) lub nowszego, możesz określić, czy działania 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 mają zastosowanie do wszystkich działań w jej stosie zadań. Jeśli na przykład aktywność główna zawiera android:resizeableActivity="true", rozmiar wszystkich aktywności w stosie zadań można zmienić. Na niektórych większych urządzeniach, np. Chromebookach, aplikacja może działać w oknie z możliwością zmiany rozmiaru, nawet jeśli określisz android:resizeableActivity="false". Jeśli spowoduje to działanie aplikacji, możesz użyć filtrów, aby ograniczyć jej dostępność na takich urządzeniach.

Android 12 (poziom interfejsu API 31) domyślnie używa trybu wielu okien. Na dużych ekranach (sw >= 600 dp) 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 aktywność może działać w trybie wielu okien.

changeableActivity

Ustaw ten atrybut w elemencie <activity> lub <application> pliku manifestu, aby włączyć lub wyłączyć tryb wielu okien w przypadku interfejsu API na poziomie 30 i niższym:

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

Jeśli ten atrybut ma wartość Prawda, aktywność można uruchomić w trybie podzielonego ekranu i swobodnej. Jeśli atrybut ma wartość false (fałsz), aktywność nie obsługuje trybu wielu okien. Jeśli ta wartość ma wartość Fałsz, a użytkownik próbuje uruchomić aktywność w trybie wielu okien, przejmuje ona cały ekran.

Jeśli aplikacja jest kierowana na interfejs API na poziomie 24 lub wyższym, ale nie określisz wartości tego atrybutu, domyślnie przyjmie on wartość „true” (prawda).

Jeśli kierujesz aplikację na interfejs API na poziomie 31 lub wyższym, ten atrybut działa inaczej na małych i dużych ekranach:

  • Duże ekrany (sw >= 600 dp): wszystkie aplikacje obsługują tryb wielu okien. Ten atrybut wskazuje, czy można zmienić rozmiar aktywności. Jeśli jest ustawiona resizeableActivity="false", aplikacja jest przełączana w tryb zgodności, gdy musi dostosować się do wymiarów wyświetlanych.
  • Małe ekrany (sw < 600 dp): jeśli resizeableActivity="true" i minimalna szerokość i minimalna wysokość aktywności spełniają wymagania trybu wielu okien, aktywność obsługuje tryb wielu okien. Jeśli ustawiona jest wartość resizeableActivity="false", aktywność nie obsługuje trybu wielu okien niezależnie od minimalnej szerokości i wysokości działania.

obsługuje obrazyW obrazie

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

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

zmiany config

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

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

Po dodaniu android:configChanges aktywność i fragmenty otrzymają wywołanie zwrotne do onConfigurationChanged(), zamiast być zniszczone i odtworzone. Możesz wtedy ręcznie aktualizować widoki danych, ponownie wczytywać zasoby i wykonywać inne operacje w razie potrzeby.

<układ>

Na Androidzie w wersji 7.0 (poziom interfejsu API 24) i nowszych element manifestu <layout> obsługuje kilka atrybutów wpływających na zachowanie aktywności w trybie wielu okien:

android:defaultHeight, android:defaultWidth
Domyślna wysokość i szerokość aktywności po uruchomieniu w trybie eksploracji swobodnej.
android:gravity
Początkowe miejsce aktywności aktywności po uruchomieniu w trybie swobodnej. Odpowiednie wartości znajdziesz w sekcji Gravity.
android:minHeight, android:minWidth
Minimalna wysokość i minimalna szerokość aktywności w trybach podzielonego ekranu i eksploracji swobodnej. Jeśli użytkownik przesunie separator w trybie podzielonego ekranu tak, aby działanie było mniejsze niż określona wartość minimalna, system przytnie ją do rozmiaru żądanego przez użytkownika.

Ten kod pokazuje, jak określić domyślny rozmiar i lokalizację aktywności oraz jej minimalny rozmiar, gdy aktywność jest wyświetlana w trybie swobodnej:

<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 aplikacji

Począwszy od Androida 7.0, system ten umożliwia obsługę aplikacji, które można uruchomić w trybie wielu okien.

Wyłączone funkcje w trybie wielu okien

W trybie wielu okien Android może wyłączyć lub zignorować funkcje, które nie dotyczą aktywności, która polega na udostępnianiu ekranu urządzenia innym aplikacjom lub aktywnościom.

Dodatkowo niektóre opcje dostosowywania interfejsu systemu są wyłączone. Na przykład aplikacje nie mogą ukrywać paska stanu, jeśli działają w trybie wielu okien (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 wielu okien:

isInMultiWindowMode()
Wskazuje, czy aktywność działa w trybie wielu okien.
isInPictureInPictureMode()

Wskazuje, czy aktywność jest w trybie obrazu w obrazie.

Uwaga: tryb obrazu w obrazie to specjalny przypadek trybu wielu okien. Jeśli myActivity.isInPictureInPictureMode() zwraca wartość „true”, myActivity.isInMultiWindowMode() zwraca też wartość „true”.

onMultiWindowModeChanged()
System wywołuje tę metodę za każdym razem, gdy aktywność przechodzi w tryb wielu okien lub z niego wychodzi. System przekazuje metodę „prawda”, jeśli aktywność wchodzi w tryb wielu okien, lub „fałsz”, jeśli opuszcza ona tryb wielu okien.
onPictureInPictureModeChanged()
System wywołuje tę metodę za każdym razem, gdy aktywność przechodzi w tryb obrazu w obrazie lub z niego wychodzi. System przekazuje metodę na wartość „prawda”, jeśli aktywność przełącza się w tryb obrazu w obrazie, lub „fałsz”, jeśli aktywność opuszcza tryb obrazu w obrazie.

Klasa Fragment ujawnia wersje wielu z tych metod, np. Fragment.onMultiWindowModeChanged().

Tryb obrazu w obrazie

Aby przełączyć aktywność w tryb obrazu w obrazie, wywołaj metodę enterPictureInPictureMode() Ta metoda nie będzie działać, jeśli urządzenie nie obsługuje trybu obraz w obrazie. Więcej informacji znajdziesz w artykule Obsługa obrazów w obrazie.

Nowe aktywności w trybie wielu okien

Gdy uruchamiasz nowe działanie, możesz określić, że ma być ono w miarę możliwości wyświetlane obok bieżącej. Użyj flagi intencji FLAG_ACTIVITY_LAUNCH_ADJACENT, która informuje system, aby spróbował utworzyć nową aktywność w sąsiednim oknie, aby 2 działania miały ten sam ekran. System stara się, aby tak się stało, ale nie możemy zagwarantować, że tak się stanie.

Jeśli urządzenie jest w trybie swobodnym i rozpoczynasz nową aktywność, możesz określić jej wymiary i lokalizację ekranu, wywołując metodę ActivityOptions.setLaunchBounds(). Ta metoda nie działa, jeśli urządzenie nie jest w trybie wielu okien.

Jeśli uruchomisz działanie w stosie zadań w interfejsie API na poziomie 30 i niższym, zastąpi ono aktywność na ekranie i dziedziczy wszystkie jej właściwości wielu okien. Jeśli chcesz uruchomić nową aktywność jako oddzielne okno w trybie wielu okien, musisz je uruchomić w nowym stosie zadań.

Android 12 (poziom interfejsu API 31) umożliwia aplikacjom dzielenie okna zadania między wiele aktywności. Aby określić, w jaki sposób aplikacja wyświetla swoje działania – na pełnym ekranie, obok siebie lub w stosie – możesz utworzyć plik konfiguracji XML lub wywołać interfejs API Jetpack WindowManager.

Przeciągnij i upuść

Użytkownicy mogą przeciągać i upuszczać dane z jednej aktywności do drugiej, gdy te dwie aktywności udostępniają ekran. W Androidzie 7.0 użytkownicy mogli przeciągać i upuszczać dane tylko w ramach jednej aktywności. Aby szybko dodać obsługę akceptowania utraconych treści, skorzystaj z interfejsu API DropHelper. Pełne wskazówki dotyczące przeciągania i upuszczania znajdziesz w sekcji Przeciąganie i upuszczanie.

Wiele instancji

Każda aktywność na poziomie głównym ma własne zadanie, które jest uruchamiane w innym procesie i wyświetlane w osobnym oknie. Aby uruchomić nową instancję aplikacji w osobnym oknie, możesz rozpocząć nowe działania za pomocą flagi FLAG_ACTIVITY_NEW_TASK. Możesz to połączyć z niektórymi atrybutami wielu okien, aby poprosić o konkretną lokalizację na potrzeby nowego okna. Na przykład aplikacja zakupowa może wyświetlać wiele okien, żeby porównać produkty.

Android 12 (poziom interfejsu API 31) umożliwia uruchamianie 2 instancji działania obok siebie w tym samym oknie zadania.

Jeśli chcesz zezwolić użytkownikom na uruchamianie kolejnej instancji aplikacji z poziomu menu z aplikacjami lub paska zadań, upewnij się, że aktywność w programie uruchamiającym ma wartość android:resizeableActivity="true" i nie korzysta z trybu uruchamiania, który uniemożliwia wiele wystąpień. Na przykład aktywność singleInstancePerTask może być utworzona wiele razy w różnych zadaniach, jeśli skonfigurowana jest zasada FLAG_ACTIVITY_MULTIPLE_TASK lub FLAG_ACTIVITY_NEW_DOCUMENT.

Nie myl instancji wielopanelowej z układem wielopanelowym, na przykład prezentacją ze szczegółami listy, która korzysta z SlidingPaneLayout, która działa w jednym oknie.

Pamiętaj, że gdy na urządzeniu składanym działa wiele instancji w oddzielnych oknach, w przypadku zmiany stanu może ona zostać wysłana w tle. Załóżmy np., że urządzenie jest rozłożone i po każdej stronie strony widocznej po przewinięciu ma 2 instancje aplikacji uruchomione w 2 oknach. Jeśli urządzenie jest złożone, jedna z instancji może zostać zamknięta, zamiast próbować dopasować okna obu instancji na mniejszym ekranie.

Weryfikacja w trybie wielu okien

Niezależnie od tego, czy kierujesz aplikację na interfejs API na poziomie 24 lub wyższym, sprawdź, jak działa ona w trybie wielu okien na wypadek, gdyby użytkownik próbował uruchomić ją w tym trybie na urządzeniu z Androidem 7.0 lub nowszym.

Urządzenia testowe

Urządzenia z Androidem 7.0 (poziom interfejsu API 24) lub nowszym obsługują tryb wielu okien.

Interfejs API na poziomie 23 lub niższym

Gdy użytkownicy próbują używać aplikacji w trybie wielu okien, system wymusza zmianę rozmiaru aplikacji, chyba że zadeklaruje ona stałą orientację.

Jeśli Twoja aplikacja nie deklaruje stałej orientacji, uruchom ją na urządzeniu z Androidem 7.0 lub nowszym i spróbuj przełączyć ją w tryb podzielonego ekranu. Sprawdź, czy przy wymuszonym zmianie rozmiaru aplikacji wrażenia użytkowników są akceptowalne.

Jeśli aplikacja deklaruje stałą orientację, spróbuj uruchomić ją w trybie wielu okien. Sprawdź, czy aplikacja pozostaje w trybie pełnoekranowym.

Poziomy API od 24 do 30

Jeśli Twoja aplikacja jest kierowana na interfejs API na poziomach od 24 do 30 i nie ma wyłączonej obsługi trybu wielu okien, sprawdź to zachowanie zarówno w trybie podzielonego ekranu, jak i swobodnego:

  • Uruchom aplikację na pełnym ekranie, a potem przełącz na tryb wielu okien, przytrzymując przycisk Ostatnie. Sprawdź, czy aplikacja przełącza się prawidłowo.
  • Uruchom aplikację bezpośrednio w trybie wielu okien i sprawdź, czy uruchamia się prawidłowo. Aby uruchomić aplikację w trybie wielu okien, naciśnij przycisk Ostatnie, naciśnij i przytrzymaj pasek tytułu aplikacji i przeciągnij ją do jednego z wyróżnionych obszarów na ekranie.
  • Zmień rozmiar aplikacji w trybie podzielonego ekranu, przeciągając separator ekranu. Sprawdź, czy rozmiar aplikacji zmienia się bez awarii i czy niezbędne elementy interfejsu są widoczne.
  • Jeśli masz określone minimalne wymiary, spróbuj zmniejszyć rozmiar aplikacji poniżej tych wymiarów. Sprawdź, czy nie możesz zmienić rozmiaru aplikacji tak, aby nie przekraczał określonych minimalnych wymiarów.
  • We wszystkich testach upewnij się, że działanie aplikacji jest akceptowalne. Sprawdź na przykład, czy po zmianie rozmiaru aplikacji nie występuje zbyt duże opóźnienie w aktualizacji interfejsu.

Poziom API 31 lub wyższy

Jeśli Twoja aplikacja jest kierowana na interfejs API na poziomie 31 lub wyższym, a minimalna szerokość i minimalna wysokość aktywności głównej są mniejsze lub równe odpowiednich wymiarów dostępnego obszaru wyświetlania, sprawdź wszystkie zachowania wymienione w sekcji dotyczącej poziomów interfejsu API od 24 do 30.

Testowa lista kontrolna

Aby sprawdzić wydajność aplikacji w trybie wielu okien, wykonaj te operacje. O ile nie zaznaczono inaczej, wypróbuj te operacje zarówno w trybie podzielonego ekranu, jak i swobodnego.

  • Włącz i zamknij tryb wielu okien.
  • Przełącz się z innej aplikacji na inną i sprawdź, czy działa ona prawidłowo, gdy jest widoczna, ale nieaktywna. Jeśli na przykład Twoja aplikacja odtwarza film, sprawdź, czy film jest nadal odtwarzany, gdy użytkownik korzysta z innej aplikacji.
  • W trybie podzielonego ekranu spróbuj przesunąć separator ekranu, aby powiększyć lub zmniejszyć aplikację. Wypróbuj te operacje obok siebie oraz jedną nad innymi konfiguracjami. Sprawdź, czy aplikacja nie ulega awarii, kluczowe funkcje są widoczne i czy operacja zmiany rozmiaru nie trwa zbyt długo.
  • Szybkie wykonywanie kilku operacji zmiany rozmiaru. Sprawdź, czy aplikacja nie ulega awarii ani nie wycieka pamięci. Narzędzie do profilowania pamięci w Android Studio dostarcza informacji o wykorzystaniu pamięci przez aplikację (patrz sekcja Sprawdzanie wykorzystania pamięci przez aplikację przy użyciu narzędzia Memory Profiler).
  • Używaj swojej aplikacji normalnie w wielu różnych konfiguracjach okien i sprawdź, czy działa ona prawidłowo. Sprawdź, czy tekst jest czytelny i czy elementy interfejsu nie są zbyt małe, aby można było z nich korzystać.

Wyłączono tryb wielu okien

Na poziomach od 24 do 30 interfejsu API, jeśli wyłączysz obsługę wielu okien w ustawieniach android:resizeableActivity="false", uruchom aplikację na urządzeniu z Androidem od 7.0 do 11 i spróbuj włączyć w niej tryb podzielonego ekranu oraz swobodny. Sprawdź, czy aplikacja pozostaje w trybie pełnoekranowym.

Dodatkowe materiały

Więcej informacji o obsłudze wielu okien w Androidzie znajdziesz w tych artykułach: