Picture-in-Picture w aplikacjach mobilnych — co to jest, jak działa i gdzie jest stosowane

Autor: IT Sectr Opublikowano: 2026-05-25 Czas czytania: 9 min

Picture-in-Picture (PiP) — tryb odtwarzania wideo w pływającym oknie nad innymi aplikacjami, pozwalający użytkownikowi kontynuować oglądanie treści przy minimalizacji aplikacji lub przełączaniu się między programami. Okno PiP automatycznie pozycjonuje się w rogu ekranu i może być przesuwane przez użytkownika. Według Apple AVPictureInPictureController documentation (2026), tryb PiP jest obsługiwany na iOS od wersji 14 i na Android od wersji 8.0.

Najważniejsze

  • Picture-in-Picture — pływające okno wideo nad innymi aplikacjami do wielozadaniowego oglądania
  • iOS PiP dostępny od iOS 14 przez AVPictureInPictureController i AVPlayer
  • Android PiP dostępny od Android 8.0 przez tryb PIP w Activity z parametrem supportsPictureInPicture
  • Ograniczenia: okno PiP ma stały rozmiar i nie obsługuje interaktywnych elementów UI
  • Zastosowanie — rozmowy wideo, streaming, platformy edukacyjne, wideo w tle

Co to jest Picture-in-Picture?

Picture-in-Picture (PiP) — to tryb wyświetlania wideo w małym pływającym oknie, które pozostaje nad wszystkimi innymi oknami i aplikacjami. Użytkownik może przesuwać okno PiP po ekranie, zmieniać jego rozmiar (na niektórych platformach) i kontynuować oglądanie treści podczas pracy w innych aplikacjach.

Koncepcja PiP pochodzi z telewizji: już w latach 90. telewizory umożliwiały wyświetlanie drugiego kanału w rogu ekranu. W urządzeniach mobilnych PiP po raz pierwszy pojawił się na iPadzie w iOS 9 (2015) dla wideo w Safari, a pełnoprawny systemowy PiP dla aplikacji stał się dostępny w iOS 14 (2020). Na Android wsparcie PiP pojawiło się wcześniej — w wersji 8.0 Oreo (2017), ale tylko dla wideo, a od Androida 12 — dla wszystkich typów treści.

PiP różni się od odtwarzania w tle tym, że wideo nadal wyświetla się na ekranie, a nie tylko odtwarza się w strumieniu audio. Odtwarzanie w tle (background audio) jest dostępne na obu platformach, ale PiP daje użytkownikowi wizualną kontrolę nad treścią: widzi klatki, może zatrzymać, przewinąć lub zamknąć okno. Jest to szczególnie ważne w przypadku lekcji wideo, streamów i rozmów wideo, gdzie treść wizualna jest równie ważna co audio.

Jak działa PiP?

Architektonicznie PiP jest realizowany przez systemowy menedżer okien, który tworzy osobne okno o niższym priorytecie wyświetlania. Aplikacja deleguje wyjście wideo do usługi systemowej, która kontynuuje renderowanie wideo nawet po przejściu aplikacji w tło lub po jej minimalizacji.

Cykl życia sesji PiP

Proces rozpoczyna się, gdy użytkownik minimalizuje aplikację z aktywnym wideo lub naciska przycisk PiP (na iOS) lub system automatycznie przełącza Activity w tryb PiP (na Android). Systemowy menedżer okien przechwytuje strumień wideo i tworzy pływające okno o stałych proporcjach. Rozmiar okna zależy od proporcji oryginalnego wideo i ograniczeń platformy: na iOS okno PiP zajmuje około 1/6–1/4 szerokości ekranu, na Android — co najmniej 108 dp szerokości i 240 dp wysokości dla urządzeń mobilnych.

Gdy okno PiP jest aktywne, aplikacja może znajdować się w jednym z trzech stanów: w tle (zminimalizowana), w stanie aktywnym (użytkownik wrócił do aplikacji) lub w stanie oczekiwania (system wstrzymał PiP z powodu braku zasobów). Przy przejściu w PiP aplikacja powinna wstrzymać niepotrzebne operacje UI (animacje, renderowanie interfejsu) i zwolnić pamięć, ponieważ zasoby systemowe w trybie wielozadaniowym są dystrybuowane bardziej restrykcyjnie. iOS automatycznie wysyła do aplikacji powiadomienie AVPictureInPictureControllerWillStartNotification, a Android — callback onPictureInPictureModeChanged.

Ograniczenia trybu PiP

Okno PiP ma istotne ograniczenia: nie można na nim wyświetlać standardowych elementów sterowania UI (przycisk pauzy, suwak postępu) — tylko minimalny systemowy overlay z podstawowymi elementami: play/pause, zamknij, rozwiń do pełnego ekranu. Systemowy UI PiP na iOS zawiera przycisk pauzy i zamknięcia, a na Android — te same elementy plus dodatkowy przycisk ustawień. Interakcja z treścią wewnątrz PiP (przewijanie, wybór napisów) jest niemożliwa — wymaga rozwinięcia aplikacji na pełny ekran.

PiP na iOS: implementacja i ograniczenia

Na iOS PiP jest zaimplementowany przez framework AVKit i klasę AVPictureInPictureController. To API jest dostępne na iOS 14+ dla iPhone i iPad, ale z różnymi wymaganiami: na iPad PiP działa przez AVPlayerLayer, na iPhone — tylko przez AVPlayerViewController.

Wymagania dla PiP na iOS

Do działania PiP na iOS należy spełnić kilka warunków: aplikacja musi używać AVPlayer do odtwarzania wideo, sesja audio musi być skonfigurowana na kategorię .playback lub .playAndRecord, a aplikacja musi posiadać entitlements dla dźwięku w tle (UIBackgroundModes = audio). Bez tych ustawień PiP nie uruchomi się — system odrzuci żądanie utworzenia sesji PiP, ponieważ nie będzie mógł zagwarantować poprawnego odtwarzania po przejściu w tło.

Na iOS okno PiP pojawia się automatycznie przy minimalizacji aplikacji, jeśli wideo jest aktywnie odtwarzane i użytkownik nie wyłączył tej funkcji w ustawieniach. Użytkownik może także ręcznie zminimalizować wideo do PiP za pomocą przycisku w AVPlayerViewController. Rozmiar okna PiP na iOS jest stały i określany przez system — deweloper nie może go zmienić. Proporcje okna PiP odpowiadają proporcjom oryginalnego wideo, ale maksymalny rozmiar jest ograniczony do 1/4 szerokości ekranu na iPhone i 1/3 na iPad.

Ograniczenia iOS PiP

Główne ograniczenia PiP na iOS: brak możliwości własnego UI w oknie PiP, ograniczenie do jednego strumienia PiP jednocześnie i wymóg aktywnego AVPlayer do działania PiP. Multi-PiP — jednoczesne odtwarzanie wielu okien PiP — nie jest obsługiwane na iOS. Przy próbie uruchomienia drugiego PiP pierwszy automatycznie się zamyka. To ograniczenie jest sprzętowe: procesor wideo nie może jednocześnie obsługiwać dwóch niezależnych kanałów PiP ze względu na ograniczenia DMA i pamięci wideo.

Kolejne ważne ograniczenie — czas odtwarzania w tle. Jeśli użytkownik nie wchodzi w interakcję z oknem PiP, system może wstrzymać odtwarzanie po pewnym czasie w celu oszczędzania energii. Automatyczna pauza PiP na iOS następuje po 10–15 minutach braku aktywności, jeśli aplikacja nie zaimplementowała mechanizmu keep-alive przez background task. W przypadku rozmów wideo i streamów zaleca się używanie PushKit i certyfikatów VoIP, które omijają to ograniczenie.

PiP na Android: implementacja i ograniczenia

Na Android PiP jest zaimplementowany jako wbudowany tryb Activity, który aktywuje się przez metodę enterPictureInPictureMode. Od Android 8.0 (API 26) każda Activity może przejść w tryb PiP, a od Android 12 (API 31) pojawiło się wsparcie PiP dla SurfaceView i TextureView bez konieczności używania MediaCodec.

Konfiguracja manifestu

Do obsługi PiP w manifeście Android należy dodać atrybut android:supportsPictureInPicture dla Activity w sekcji . Bez tego atrybutu system nie zezwoli na przejście w PiP. Dodatkowo zaleca się dodanie android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation", aby Activity nie była odtwarzana przy zmianie rozmiaru okna podczas przejścia w PiP. Kompilacja musi mieć targetSdkVersion >= 26 (Android 8.0) do działania podstawowego PiP.

W Android okno PiP domyślnie nie ma elementów sterowania. Deweloper może dodać niestandardowe akcje przez RemoteAction w metodzie setPictureInPictureParams. Dostępne są do 3 akcji (np.: pauza/odtwórz, przewiń wstecz/do przodu, zamknij). Każda akcja wyświetla się w systemowym overlay PiP jako ikona. W przeciwieństwie do iOS, gdzie wszystkie elementy UI są ściśle ustalone, Android daje więcej elastyczności w zakresie podstawowych kontrolek.

Adaptacja do różnych wersji

PiP na Android ma różne możliwości w zależności od wersji systemu. Na Android 8.0–8.1 PiP jest dostępny tylko dla wideo odtwarzanego przez MediaPlayer lub MediaCodec z SurfaceView. Od Android 9 można używać PictureInPictureArgs.Builder do konfiguracji proporcji okna PiP. Android 12 dodał obsługę PiP dla niestandardowych SurfaceView i TextureView, a także ulepszone zarządzanie przejściami między pełnym ekranem a trybem PiP. Android 13+ umożliwia wyświetlanie okna PiP nawet przy zablokowanym ekranie, jeśli aplikacja ma odpowiednie uprawnienia.

Wersja AndroidMożliwości PiPAPI
8.0–8.1Podstawowy PiP dla MediaPlayer/MediaCodec26–27
9–11Konfiguracja proporcji, niestandardowe akcje28–30
12Obsługa SurfaceView/TextureView w PiP31
13+PiP na ekranie blokady, ulepszone animacje33+

Kluczowa różnica Android PiP od iOS — możliwość multi-PiP. Na Android od wersji 12 system może wyświetlać kilka okien PiP jednocześnie, jeśli aplikacje to obsługują i wydajność urządzenia na to pozwala. W praktyce jednak multi-PiP jest ograniczony możliwościami SoC: większość urządzeń obsługuje tylko jedno okno PiP ze względu na ograniczenia sprzętowe dekodera, ponieważ każde okno PiP wymaga własnego strumienia wideo i oddzielnej sesji dekodowania.

Przykłady kodu PiP

Rozważmy praktyczną implementację PiP na obu platformach mobilnych z uwzględnieniem najnowszych zmian API.

PiP na iOS z AVPictureInPictureController

swift
import AVKit
import AVFoundation

class VideoPlayerViewController: UIViewController {
    var player: AVPlayer!
    var pipController: AVPictureInPictureController?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        let playerLayer = AVPlayerLayer(player: player)
        playerLayer.videoGravity = .resizeAspect
        view.layer.addSublayer(playerLayer)
        
        guard AVPictureInPictureController.isPictureInPictureSupported()
        else { return }
        
        pipController = AVPictureInPictureController(playerLayer: playerLayer)
        pipController?.delegate = self
    }
    
    @IBAction func startPiPTapped() {
        pipController?.startPictureInPicture()
    }
}

extension VideoPlayerViewController: AVPictureInPictureControllerDelegate {
    func pictureInPictureControllerWillStart(
        _ pictureInPictureController: AVPictureInPictureController
    ) {
        // Ukryj elementy UI, zwolnij pamięć
    }
    
    func pictureInPictureControllerDidStop(
        _ pictureInPictureController: AVPictureInPictureController
    ) {
        // Przywróć UI, wznowić renderowanie
    }
}

W przykładzie AVPictureInPictureController jest inicjalizowany z playerLayer po sprawdzeniu isPictureInPictureSupported (PiP nie jest obsługiwany na iPhone SE 1. generacji i niektórych iPadach bez wystarczającej pamięci). Delegat powiadamia aplikację o rozpoczęciu i zakończeniu PiP — w tych callbackach należy ukryć i przywrócić elementy UI, ponieważ w trybie PiP interfejs aplikacji nie jest widoczny. Przy przejściu w PiP zaleca się zatrzymanie wszystkich animacji, ukrycie kontrolek odtwarzacza i zwolnienie nieużywanej pamięci, aby zapobiec wymuszonemu wyładowaniu aplikacji przez system.

PiP na Android z PictureInPictureParams

kotlin
class PipVideoActivity : AppCompatActivity() {
    
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setupVideoPlayer()
    }
    
    private fun enterPipMode() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            val aspectRatio = Rational(16, 9)
            
            val pipParams = PictureInPictureParams.Builder()
                .setAspectRatio(aspectRatio)
                .setAutoEnterEnabled(true)
                .build()
            
            enterPictureInPictureMode(pipParams)
        }
    }
    
    override fun onPictureInPictureModeChanged(
        isInPictureInPictureMode: Boolean,
        newConfig: Configuration
    ) {
        if (isInPictureInPictureMode) {
            // Ukryj UI, skup się tylko na mediach
            binding.controlsGroup.visibility = View.GONE
        } else {
            // Przywróć UI
            binding.controlsGroup.visibility = View.VISIBLE
        }
    }
}

Przykład w Kotlin używa PictureInPictureParams.Builder do konfiguracji PiP. Metoda setAspectRatio ustawia proporcje okna PiP (16:9 dla typowego wideo). setAutoEnterEnabled(true) włącza automatyczne przejście w PiP przy minimalizacji aplikacji. Callback onPictureInPictureModeChanged jest wywoływany przy wejściu i wyjściu z PiP — w nim należy ukrywać lub pokazywać elementy UI. Dla wideo na SurfaceView wymagane jest dodatkowe obsłużenie konfiguracji poprzez dodanie android:configChanges="screenSize|smallestScreenSize" w manifeście, aby zapobiec odtworzeniu Activity przy przejściu w tryb PiP.

Kiedy używać Picture-in-Picture

PiP to potężne narzędzie do poprawy doświadczenia użytkownika w aplikacjach, gdzie treść pozostaje istotna nawet przy przełączaniu się na inne zadania. Jednak wdrożenie PiP powinno być uzasadnione i nie rozpraszać użytkownika.

Optymalne scenariusze

Rozmowy wideo i konferencje — jeden z głównych scenariuszy PiP. W Zoom, FaceTime, Google Meet PiP pozwala widzieć rozmówcę podczas pracy w innych aplikacjach: czytania notatek, przeglądania prezentacji lub sprawdzania poczty. PiP dla rozmów wideo wymaga obsługi kamery w tle i prawidłowej konfiguracji sesji audio do kontynuacji przechwytywania dźwięku w tle. Na iOS używa się do tego AVSampleBufferDisplayLayer zamiast AVPlayerLayer, ponieważ rozmowy wideo nie używają AVPlayer.

Serwisy streamingowe (YouTube, Netflix, Twitch) aktywnie używają PiP do kontynuacji oglądania podczas szukania nowych treści. YouTube Premium oferuje PiP jako płatną funkcję, Netflix również ogranicza PiP do określonych planów taryfowych ze względu na licencyjne ograniczenia treści. Do implementacji PiP w aplikacji streamingowej wymagana jest integracja z systemem DRM (FairPlay, Widevine), który obsługuje bezpieczny pipeline w trybie PiP.

Kiedy PiP nie jest potrzebny

PiP nie nadaje się do aplikacji z interaktywną treścią wideo, gdzie wymagana jest interakcja użytkownika: platformy edukacyjne z testami w odtwarzaczu, streamy gier z czatem, aplikacje zakupowe z linkami do produktów w wideo. W tych przypadkach okno PiP jest zbyt małe do wyświetlania dodatkowych informacji, a interaktywne elementy w PiP nie są obsługiwane przez system. Zaleca się używanie PiP tylko do pasywnego oglądania, gdy interakcja z treścią nie jest wymagana.

Dla aplikacji muzycznych i podcastów PiP jest zbędny — wystarczy dźwięk w tle bez okna wizualnego. PiP zużywa dodatkowe zasoby GPU do renderowania wideo w pływającym oknie, co skraca czas pracy na baterii. Jeśli treść jest audialna (muzyka, podcasty, audiobooki) — używaj odtwarzania w tle bez PiP. Jeśli wizualna — wdrażaj PiP dla poprawy doświadczenia użytkownika.

Często zadawane pytania

Dlaczego PiP nie działa na moim iPhone?

PiP na iOS wymaga iPhone 6s+, iOS 14+ i regionu z obsługą (USA, Kanada, Australia, UE, Rosja i inne). Dla aplikacji należy skonfigurować audio session na kategorię .playback i dodać UIBackgroundModes = audio. Sprawdź także ustawienia: Ustawienia > Ogólne > Obraz w obrazie.

Czy można ustawić rozmiar okna PiP?

Na iOS rozmiar okna PiP jest całkowicie określany przez system i nie jest konfigurowany przez dewelopera. Na Android można ustawić tylko proporcje przez setAspectRatio w PictureInPictureParams.Builder, ale dokładny rozmiar okna określa system. Użytkownik może zmienić rozmiar okna PiP na Android 12+ gestem pinch-to-zoom.

Czy PiP działa z treścią DRM?

Tak, PiP działa z treścią chronioną DRM (FairPlay na iOS, Widevine L1 na Android) pod warunkiem, że sesja DRM obsługuje bezpieczny pipeline w trybie PiP. Widevine L3 może nie obsługiwać PiP, ponieważ nie gwarantuje bezpieczeństwa zdekodowanej treści w pływającym oknie. Sprawdzaj kompatybilność DRM z PiP na etapie testowania.

Ile okien PiP można otworzyć jednocześnie?

Na iOS — tylko jedno okno PiP. Na Android 12+ teoretycznie obsługiwany jest multi-PiP, ale w praktyce większość urządzeń jest ograniczona do jednego okna ze względu na ograniczenia sprzętowe. Urządzenia z najwyższej półki (Samsung Galaxy S24, Pixel 8) mogą obsługiwać 2 okna PiP, ale z obniżoną wydajnością.

Czy trzeba obsługiwać lifecycle przy PiP?

Tak, obsługa lifecycle jest krytyczna. Na iOS przy przejściu w PiP aplikacja otrzymuje powiadomienie willStart, gdzie należy ukryć UI i zwolnić pamięć. Na Android onPictureInPictureModeChanged jest wywoływany przy wejściu/wyjściu z PiP. Przy nieprawidłowej obsłudze lifecycle system może wyładować aplikację z pamięci, przerywając odtwarzanie.

Podsumowanie

  • Picture-in-Picture — pływające okno do oglądania wideo nad innymi aplikacjami w trybie wielozadaniowym
  • PiP na iOS jest realizowany przez AVPictureInPictureController z AVPlayerLayer i audio session .playback
  • PiP na Android jest realizowany przez enterPictureInPictureMode z PictureInPictureParams.Builder
  • Ograniczenia: jeden strumień PiP, stały rozmiar okna, brak własnego UI wewnątrz PiP
  • Lifecycle przy PiP wymaga ukrycia elementów UI i zwolnienia pamięci, aby zapobiec wyładowaniu
  • Główne scenariusze — rozmowy wideo, streaming, filmy edukacyjne, oglądanie treści podczas nawigacji
  • Nie używaj PiP dla treści audio (wystarczy dźwięk w tle) lub interaktywnych wideo z elementami UI

Opracujemy aplikację mobilną pod klucz

IT Sectr tworzy aplikacje na iOS i Androida dla startupów i firm od 2017 roku. Doradzimy Ci i zaproponujemy najlepsze rozwiązanie.

Omów projekt

Przeczytaj również