Począwszy od Androida 8.0 (poziom interfejsu API 26), Android umożliwia uruchamianie działań tryb obrazu w obrazie (PIP). Obraz w obrazie to specjalny typ trybu wielu okien, używany do odtwarzania filmów. Pozwala użytkownikowi obejrzeć film w przypiętym małym oknie w rogu ekranu podczas przechodzenia między aplikacjami lub przeglądania treści na ekranie głównym.
Obraz w obrazie wykorzystuje interfejsy API trybu wielu okien dostępne na Androidzie 7.0, przypiętego okna nakładki wideo. Aby dodać obraz w obrazie do aplikacji, musisz zarejestrować aktywności obsługujących obraz w obrazie (PIP), w razie potrzeby przełączaj aktywność na tryb obraz w obrazie; Upewnij się, że elementy interfejsu są ukryte, a film jest nadal odtwarzany, gdy jest w trybie PIP.
Okno obrazu w obrazie pojawia się w najwyższej warstwie ekranu, w rogu wybranym przez w systemie.
Obraz w obrazie jest też obsługiwany na zgodnych urządzeniach z systemem operacyjnym Android TV Android 14 (poziom interfejsu API 34) lub nowszy. Istnieje wiele podobieństw, ale warto wziąć pod uwagę dodatkowe kwestie, PIP na telewizorze
Jak użytkownicy mogą korzystać z okna obrazu w obrazie
Użytkownicy mogą przeciągnąć okno PIP w inne miejsce. Użytkownicy Androida od wersji 12 mogą też:
Kliknij raz okno, aby wyświetlić przełącznik trybu pełnoekranowego, przycisk zamykania, przycisk ustawień i działania niestandardowe udostępniane przez aplikację (np. odtworzenie ).
Dotknij dwukrotnie okna, aby przełączyć się między bieżącym a maksymalnym rozmiarem obrazu w obrazie lub minimalny rozmiar obrazu w obrazie, np. dwukrotne kliknięcie zmaksymalizowanego okna. który go minimalizuje i jednocześnie działa odwrotność.
Ukryj okno, przeciągając je do lewej lub prawej krawędzi. Aby przywrócić kliknij widoczną część schowka lub przeciągnij je poza nie.
Powiększ lub ściągnij palce, aby zmienić rozmiar okna funkcji obraz w obrazie.
Aplikacja określa, kiedy bieżąca aktywność przechodzi w tryb obrazu w obrazie. Oto kilka Przykłady:
Aktywność może przejść w tryb obrazu w obrazie, gdy użytkownik naciśnie przycisk ekranu głównego lub przesunie palcem na ekranie głównym do domu. W ten sposób Mapy Google nadal wyświetlają wskazówki dojazdu, gdy użytkownik wykonuje w tym samym czasie inną aktywność.
Aplikacja może przenieść film do trybu obraz w obrazie, gdy użytkownik wróci z powrotem go, aby przeglądać inne treści.
Aplikacja może przełączać film w tryb obrazu w obrazie, gdy użytkownik ogląda do końca danego odcinka serialu. Ekran główny wyświetla promocję lub podsumowanie. informacji na temat następnego odcinka serialu.
Twoja aplikacja może umożliwiać użytkownikom dodawanie do kolejki dodatkowych treści, oglądają film. Film jest nadal odtwarzany w trybie obraz w obrazie podczas głównego na ekranie wyświetla się aktywność dotycząca wyboru treści.
Zadeklaruj obsługę obrazu w obrazie
Domyślnie system nie obsługuje automatycznie funkcji PIP w aplikacjach. Jeśli chcesz
obsługuje funkcję PIP w aplikacji, zarejestruj aktywność związaną z filmami w pliku manifestu przez
ustawiam wartość true
w polu android:supportsPictureInPicture
. Określ też, że
aktywność obsługuje zmiany w konfiguracji układu, dzięki czemu aktywność
jest uruchamiany ponownie po zmianie układu w trakcie przechodzenia w trybie obrazu w obrazie.
<activity android:name="VideoActivity"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...
Przełącz aktywność na obraz w obrazie
Począwszy od Androida 12, można przełączyć aktywność w tryb obraz w obrazie za pomocą:
flagę setAutoEnterEnabled
do true
. Przy tym ustawieniu aktywność
w razie potrzeby automatycznie przełącza się na tryb PIP bez konieczności jawnego wywoływania
enterPictureInPictureMode()
w onUserLeaveHint
. Ten element
dodatkowo płynniejsze przejścia. Szczegółowe informacje znajdziesz w artykule Tworzenie
przejście z nawigacji przy użyciu gestów do trybu PIP będzie płynniejsze.
Jeśli kierujesz aplikację na Androida 11 lub starszego, aktywność musi wywołać
enterPictureInPictureMode()
aby przejść do trybu obraz w obrazie. Na przykład ten kod przełącza aktywność na
Tryb obrazu w obrazie, gdy użytkownik kliknie specjalny przycisk w interfejsie aplikacji:
Kotlin
override fun onActionClicked(action: Action) { if (action.id.toInt() == R.id.lb_control_picture_in_picture) { activity?.enterPictureInPictureMode() return } }
Java
@Override public void onActionClicked(Action action) { if (action.getId() == R.id.lb_control_picture_in_picture) { getActivity().enterPictureInPictureMode(); return; } ... }
Możesz dodać funkcje logiczne, które przełączają aktywność w tryb PIP.
znajduje się w tle. Na przykład Mapy Google przełączają się na tryb obrazu w obrazie, jeśli
użytkownik naciska przycisk ekranu głównego lub przycisk Ostatnie podczas korzystania z aplikacji. Dostępne opcje
wykrywaj ten przypadek, zastępując
onUserLeaveHint()
:
Kotlin
override fun onUserLeaveHint() { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode() } }
Java
@Override public void onUserLeaveHint () { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode(); } }
Zalecane: zapewnij użytkownikom dopracowane przejście w trybie PIP
W Androidzie 12 wprowadzono istotne ulepszenia kosmetyczne w animowanych przejściach. między pełnym ekranem a oknami PIP. Zdecydowanie zalecamy wdrożenie wszystkich obowiązujące zmiany; zmiany te są automatycznie skalowane na dużych ekranach, takich jak urządzenia składane i tablety, bez żadnych dodatkowych działań.
Jeśli Twoja aplikacja nie zawiera odpowiednich aktualizacji, przejścia w obrazie obrazu będą nadal wykonywane działa, ale animacje są mniej dopracowane. Na przykład przejście z pełnego ekranu do trybu PIP może spowodować, że okno zanim pojawi się ponownie po zakończeniu przejścia.
Obejmują one następujące elementy.
- Płynniejsze przejście z nawigacji przy użyciu gestów do trybu obraz w obrazie
- Ustawiam właściwą wartość
sourceRectHint
umożliwiającą włączanie i wyłączanie trybu obraz w obrazie - Wyłączanie płynnej zmiany rozmiaru w przypadku treści innych niż wideo
Patrz: Android Próbka obrazu w obrazie Kotlin jako materiał referencyjny umożliwiający dopracowanie przejścia.
Płynniejsze przejście do trybu PIP z nawigacji przy użyciu gestów
Począwszy od Androida 12 flaga setAutoEnterEnabled
zapewnia wiele
płynniejsza animacja przy przechodzeniu do treści wideo w trybie obraz w obrazie za pomocą gestu
nawigacji, np. podczas przesuwania w górę strony głównej z pełnego ekranu.
Wykonaj poniższe czynności, aby wprowadzić tę zmianę. Zapoznaj się z tym przykładem, aby uzyskać odniesienie:
Używaj
setAutoEnterEnabled
do tworzeniaPictureInPictureParams.Builder
:Kotlin
setPictureInPictureParams(PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) .setSourceRectHint(sourceRectHint) .setAutoEnterEnabled(true) .build())
Java
setPictureInPictureParams(new PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) .setSourceRectHint(sourceRectHint) .setAutoEnterEnabled(true) .build());
Zadzwoń pod numer
setPictureInPictureParams
i podaj aktualne informacjePictureInPictureParams
przed czasem. Aplikacja nie czeka naonUserLeaveHint
– wywołanie zwrotne (tak jak w Androidzie 11).Możesz np. zadzwonić do:
setPictureInPictureParams
pierwsze odtworzenie, a kolejne odtworzenie, jeśli format obrazu zostanie zmieniony.Zadzwoń pod numer
setAutoEnterEnabled(false)
, ale tylko wtedy, gdy jest to konieczne. Przykład: To dobry pomysł, by włączyć obraz w obrazie, jeśli bieżący film jest wstrzymany. stanu.
Ustaw odpowiednią wartość sourceRectHint
umożliwiającą włączanie i wyłączanie trybu PIP
Od wprowadzenia PIP w Androidzie 8.0: setSourceRectHint
wskazać obszar aktywności, który jest widoczny po przejściu na
obraz w obrazie – np. granice wyświetlenia filmu w odtwarzaczu.
W Androidzie 12 system używa funkcji sourceRectHint
, aby zapewnić znacznie płynniejsze działanie
ani na animację.
Aby prawidłowo ustawić sourceRectHint
na potrzeby włączania i wyłączania trybu obraz w obrazie:
Utwórz
PictureInPictureParams
z użyciem prawidłowych granic, takich jaksourceRectHint
. Zalecamy również załączenie detektor zmiany układu w odtwarzaczu:Kotlin
val mOnLayoutChangeListener = OnLayoutChangeListener { v: View?, oldLeft: Int, oldTop: Int, oldRight: Int, oldBottom: Int, newLeft: Int, newTop: Int, newRight: Int, newBottom: Int -> val sourceRectHint = Rect() mYourVideoView.getGlobalVisibleRect(sourceRectHint) val builder = PictureInPictureParams.Builder() .setSourceRectHint(sourceRectHint) setPictureInPictureParams(builder.build()) } mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener)
Java
private final View.OnLayoutChangeListener mOnLayoutChangeListener = (v, oldLeft, oldTop, oldRight, oldBottom, newLeft, newTop, newRight, newBottom) -> { final Rect sourceRectHint = new Rect(); mYourVideoView.getGlobalVisibleRect(sourceRectHint); final PictureInPictureParams.Builder builder = new PictureInPictureParams.Builder() .setSourceRectHint(sourceRectHint); setPictureInPictureParams(builder.build()); }; mYourVideoView.addOnLayoutChangeListener(mOnLayoutChangeListener);
W razie potrzeby zaktualizuj
sourceRectHint
, zanim system rozpocznie przejścia. Gdy system niedługo wyjdzie z trybu obraz w obrazie, aktywność hierarchia widoków jest ułożona zgodnie z konfiguracją miejsca docelowego (na przykład pełny ekran). Aplikacja może dołączyć detektor zmian układu do widoku głównego lub obejrzenie reklamy (np. obejrzenie odtwarzacza wideo), aby wykryć zdarzenie oraz zaktualizuj elementsourceRectHint
przed rozpoczęciem animacji.Kotlin
// Listener is called immediately after the user exits PiP but before animating. playerView.addOnLayoutChangeListener { _, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom -> if (left != oldLeft || right != oldRight || top != oldTop || bottom != oldBottom) { // The playerView's bounds changed, update the source hint rect to // reflect its new bounds. val sourceRectHint = Rect() playerView.getGlobalVisibleRect(sourceRectHint) setPictureInPictureParams( PictureInPictureParams.Builder() .setSourceRectHint(sourceRectHint) .build() ) } }
Java
// Listener is called right after the user exits PiP but before // animating. playerView.addOnLayoutChangeListener((v, left, top, right, bottom, oldLeft, oldTop, oldRight, oldBottom) -> { if (left != oldLeft || right != oldRight || top != oldTop || bottom != oldBottom) { // The playerView's bounds changed, update the source hint rect to // reflect its new bounds. final Rect sourceRectHint = new Rect(); playerView.getGlobalVisibleRect(sourceRectHint); setPictureInPictureParams( new PictureInPictureParams.Builder() .setSourceRectHint(sourceRectHint) .build()); } });
Wyłącz płynną zmianę rozmiaru w przypadku treści innych niż wideo
Android 12 dodaje flagę setSeamlessResizeEnabled
, która zapewnia
płynniejsza animacja przenikania przy zmianie rozmiaru treści innych niż wideo w obrazie w obrazie
okno. Wcześniej zmiana rozmiaru treści innych niż wideo w oknie PIP mogła spowodować
zaciemnianie elementów wizualnych.
Aby wyłączyć płynną zmianę rozmiaru w przypadku treści innych niż wideo:
Kotlin
setPictureInPictureParams(PictureInPictureParams.Builder() .setSeamlessResizeEnabled(false) .build())
Java
setPictureInPictureParams(new PictureInPictureParams.Builder() .setSeamlessResizeEnabled(false) .build());
Obsługa interfejsu podczas obrazu w obrazie
Po uruchomieniu lub zamknięciu trybu obraz w obrazie system wywołuje
Activity.onPictureInPictureModeChanged()
lub
Fragment.onPictureInPictureModeChanged()
Te wywołania zwrotne należy zastąpić, aby ponownie wykorzystać elementy interfejsu aktywności. Google Keep pamiętaj, że w trybie PIP Twoja aktywność jest wyświetlana w małym oknie. Użytkownicy nie mogą interakcji z elementami interfejsu aplikacji, gdy jest ona w trybie Obraz w obrazie, oraz małe elementy interfejsu mogą być niewidoczne. Odtwarzanie filmów z minimalistyczny interfejs użytkownika zapewnia użytkownikom najlepsze wrażenia.
Jeśli aplikacja musi udostępniać niestandardowe działania dla obrazu w obrazie, zapoznaj się z sekcją Dodawanie na tej stronie. Usuń inne elementy interfejsu przed aktywność przechodzi w obraz w obrazie i jest przywracana po włączeniu trybu pełnoekranowego ponownie:
Kotlin
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) { if (isInPictureInPictureMode) { // Hide the full-screen UI (controls, etc.) while in PiP mode. } else { // Restore the full-screen UI. } }
Java
@Override public void onPictureInPictureModeChanged (boolean isInPictureInPictureMode, Configuration newConfig) { if (isInPictureInPictureMode) { // Hide the full-screen UI (controls, etc.) while in PiP mode. } else { // Restore the full-screen UI. ... } }
Dodaj elementy sterujące
Okno obrazu w obrazie może zawierać elementy sterujące, gdy użytkownik otworzy menu okna (przez dotykając okna na komórce lub wybierając menu z telewizora zdalnie).
Jeśli aplikacja ma aktywne multimedia sesja, a następnie odtwarzanie, pojawią się elementy sterujące, by wstrzymać, dalej i wstecz.
Możesz również bezpośrednio określić działania niestandardowe, tworząc
PictureInPictureParams
z
PictureInPictureParams.Builder.setActions()
przed przejściem w tryb obrazu w obrazie oraz przekazać parametry po przejściu w tryb
enterPictureInPictureMode(android.app.PictureInPictureParams)
lub
setPictureInPictureParams(android.app.PictureInPictureParams)
.
Zachowaj ostrożność. Jeśli spróbujesz dodać więcej niż
getMaxNumPictureInPictureActions()
otrzymasz tylko maksymalną liczbę.
Kontynuuję odtwarzanie filmu w trybie obraz w obrazie
Gdy aktywność przełączy się na obraz w obrazie, system umieszcza ją w
i wywołuje metodę
onPause()
. Wideo
odtwarzanie nie powinno być wstrzymywane. Zamiast tego można je kontynuować, jeśli aktywność jest
wstrzymano podczas przechodzenia w tryb obrazu w obrazie.
W Androidzie 7.0 i nowszych należy wstrzymywać i wznawiać odtwarzanie filmu, gdy
system wywołuje metodę
onStop()
i
onStart()
W ten sposób
można uniknąć sprawdzania, czy aplikacja działa w trybie PIP w trybie onPause()
oraz
konkretne kontynuowanie odtwarzania.
Jeśli flaga setAutoEnterEnabled
nie jest ustawiona na true
i musisz:
wstrzymaj odtwarzanie w swojej implementacji onPause()
, sprawdź tryb obrazu w obrazie, wywołując
isInPictureInPictureMode()
i odpowiednio obsługuj odtwarzanie. Na przykład:
Kotlin
override fun onPause() { super.onPause() // If called while in PiP mode, do not pause playback if (isInPictureInPictureMode) { // Continue playback } else { // Use existing playback logic for paused Activity behavior. } }
Java
@Override public void onPause() { // If called while in PiP mode, do not pause playback if (isInPictureInPictureMode()) { // Continue playback ... } else { // Use existing playback logic for paused Activity behavior. ... } }
Gdy aktywność przełączy się z powrotem na tryb pełnoekranowy, system
wznowi aktywność i zadzwoni na
onResume()
.
Używaj pojedynczej aktywności związanej z odtwarzaniem na potrzeby funkcji PIP
Użytkownik może wybrać nowy film podczas przeglądania treści w aplikacji. ekran główny, podczas gdy odtwarzana jest aktywność wideo w trybie PIP. Odtwórz nowy film w istniejącej aktywności związanej z odtwarzaniem w trybie pełnoekranowym, zamiast uruchamiać nowe działanie, które może zdezorientować użytkownika.
Aby mieć pewność, że pojedyncza aktywność będzie używana do żądań odtwarzania filmów i przełączana
włącz lub wyłącz tryb PIP odpowiednio do potrzeb, ustaw android:launchMode
aktywności na
singleTask
w pliku manifestu:
<activity android:name="VideoActivity"
...
android:supportsPictureInPicture="true"
android:launchMode="singleTask"
...
W aktywności zastąp
onNewIntent()
i włączyć odtwarzanie nowego filmu, w razie potrzeby zatrzymując odtwarzanie istniejącego.
Sprawdzone metody
Obraz w obrazie może być wyłączony na urządzeniach z małą ilością pamięci RAM. Zanim aplikacja zacznie korzystać z PIP:
aby sprawdzić dostępność usługi, zadzwoń pod numer
hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
Obraz w obrazie jest przeznaczony do działań, w których odtwarzane są filmy na pełnym ekranie. Podczas zmiany w trybie PIP, unikaj wyświetlania niczego oprócz treści wideo. Śledź, gdy aktywność przechodzi w tryb PIP i ukrywa elementy interfejsu zgodnie z opisem w sekcji Obsługa interfejsu użytkownika podczas obrazu w obrazie.
Gdy aktywność jest w trybie obrazu w obrazie, domyślnie nie jest ona zaznaczona. Do
odbieraj zdarzenia wejściowe w trybie obraz w obrazie, użyj
MediaSession.setCallback()
Więcej informacji o używaniu funkcji setCallback()
znajdziesz w sekcji Wyświetlanie funkcji Co jest grane
.
Gdy aplikacja jest w trybie PIP, odtwarzanie filmu w jej oknie może powodować odtwarzanie dźwięku zakłócenia działania innej aplikacji, np. odtwarzacza muzyki lub aplikacji do wyszukiwania głosowego. Aby tego uniknąć, poproś o uaktywnienie dźwięku po rozpoczęciu odtwarzania filmu i ustaw powiadomienia o zmianie skupienia dźwięku, zgodnie z opisem w sekcji Zarządzanie dźwiękiem Ostrość. Jeśli otrzymasz powiadomienie utraty ostrości dźwięku w trybie obrazu w obrazie, wstrzymać lub zatrzymać odtwarzanie filmu.
Pamiętaj, że gdy aplikacja ma przejść do trybu obrazu w obrazie, uwzględniana jest tylko najlepsza aktywność.
obraz w obrazie. W niektórych sytuacjach, na przykład na urządzeniach z trybem wielu okien,
możliwe, że poniższa aktywność będzie teraz wyświetlana i ponownie widoczna obok:
działania funkcji obraz w obrazie. Należy odpowiednio zająć się tą sprawą, łącznie z
aktywność poniżej, czyli otrzymanie wywołania zwrotnego onResume()
lub onPause()
. Jest także
jest możliwe, że użytkownik będzie mógł wejść w interakcję z aktywnością. Jeśli na przykład masz
aktywność związaną z listą filmów oraz aktywność związaną z odtwarzaniem filmów w trybie obrazu w pionie,
użytkownik może wybrać nowy film z listy, co spowoduje zaktualizowanie aktywności obrazu w obrazie
odpowiednio się zmienia.
Dodatkowy przykładowy kod
Aby pobrać przykładową aplikację napisaną w języku Kotlin, zobacz Android PictureInPicture Sample. (Kotlin).