Picture-in-Picture (PiP) — ett läge för videouppspelning i ett flytande fönster ovanför andra appar, som låter användaren fortsätta titta på innehåll när appen minimeras eller när man växlar mellan program. PiP-fönstret placeras automatiskt i hörnet av skärmen och kan flyttas av användaren. Enligt Apple AVPictureInPictureController documentation (2026) stöds PiP-läget på iOS från version 14 och på Android från version 8.0.
Huvudpunkter
Picture-in-Picture (PiP) är ett läge för att visa video i ett litet flytande fönster som stannar ovanför alla andra fönster och appar. Användaren kan flytta PiP-fönstret på skärmen, ändra dess storlek (på vissa plattformar) och fortsätta titta på innehåll medan de arbetar i andra appar.
Konceptet PiP kommer från televisionen: redan på 1990-talet kunde tv-apparater visa en andra kanal i hörnet av skärmen. I mobila enheter dök PiP först upp på iPad i iOS 9 (2015) för video i Safari, och fullt system-PiP för appar blev tillgängligt i iOS 14 (2020). På Android dök PiP-stöd upp tidigare — i version 8.0 Oreo (2017), men bara för video, och från Android 12 för alla typer av innehåll.
PiP skiljer sig från bakgrundsuppspelning genom att videon fortsätter att visas på skärmen, inte bara spelas upp i ljudströmmen. Bakgrundsuppspelning (background audio) finns på båda plattformarna, men PiP ger användaren visuell kontroll över innehållet: de ser bildrutor, kan pausa, spola tillbaka eller stänga fönstret. Detta är särskilt viktigt för videolektioner, streams och videosamtal där visuellt innehåll är lika viktigt som ljud.
Arkitektoniskt implementeras PiP via systemets fönsterhanterare som skapar ett separat fönster med lägre visningsprioritet. Appen delegerar videoutgången till en systemtjänst som fortsätter att rendera videon även efter att appen går i bakgrundsläge eller minimeras.
Processen börjar när användaren minimerar appen med aktiv video eller trycker på PiP-knappen (på iOS) eller systemet automatiskt överför Activity till PiP-läge (på Android). Systemets fönsterhanterare fångar videoströmmen och skapar ett flytande fönster med fasta proportioner. Fönstrets storlek beror på originalvideons bildförhållande och plattformens begränsningar: på iOS upptar PiP-fönstret ungefär 1/6–1/4 av skärmbredden, på Android — minst 108 dp bredd och 240 dp höjd för mobila enheter.
När PiP-fönstret är aktivt kan appen vara i ett av tre tillstånd: i bakgrunden (minimerad), i aktivt tillstånd (användaren har återvänt till appen) eller i vänteläge (systemet har pausat PiP på grund av resursbrist). Vid övergång till PiP bör appen pausa onödiga UI-operationer (animationer, gränssnittsrendering) och frigöra minne, eftersom systemresurser i multitasking-läge fördelas striktare. iOS skickar automatiskt meddelandet AVPictureInPictureControllerWillStartNotification till appen, och Android — callbacken onPictureInPictureModeChanged.
PiP-fönstret har betydande begränsningar: det kan inte visa standard UI-kontroller (pausknapp, förloppsreglage) — endast minimal systemöverlagring med grundläggande element: play/pause, stäng, expandera till helskärm. Systemets PiP-UI på iOS innehåller en paus- och stängknapp, och på Android — samma element plus en extra inställningsknapp. Interaktion med innehåll inuti PiP (spola, välja undertexter) är inte möjlig — för detta måste appen öppnas i helskärm.
På iOS implementeras PiP via AVKit-ramverket och klassen AVPictureInPictureController. Detta API är tillgängligt på iOS 14+ för iPhone och iPad, men med olika krav: på iPad fungerar PiP via AVPlayerLayer, på iPhone — endast via AVPlayerViewController.
För att PiP ska fungera på iOS måste flera villkor uppfyllas: appen måste använda AVPlayer för videouppspelning, ljudsessionen måste konfigureras till kategorin .playback eller .playAndRecord, och appen måste ha behörigheter för bakgrundsljud (UIBackgroundModes = audio). Utan dessa inställningar startar inte PiP — systemet avvisar begäran om att skapa en PiP-session eftersom det inte kan garantera korrekt uppspelning efter övergång till bakgrunden.
På iOS visas PiP-fönstret automatiskt när appen minimeras om videon spelas upp aktivt och användaren inte har inaktiverat denna funktion i inställningarna. Användaren kan också manuellt minimera videon till PiP via knappen i AVPlayerViewController. Storleken på PiP-fönstret på iOS är fast och bestäms av systemet — utvecklaren kan inte ändra den. PiP-fönstrets bildförhållande motsvarar originalvideons bildförhållande, men den maximala storleken är begränsad till 1/4 av skärmbredden på iPhone och 1/3 på iPad.
De viktigaste begränsningarna för PiP på iOS: omöjlighet till anpassat UI i PiP-fönstret, begränsning till en PiP-ström samtidigt och krav på aktiv AVPlayer för PiP. Multi-PiP — samtidig uppspelning av flera PiP-fönster — stöds inte på iOS. Vid försök att starta en andra PiP stängs den första automatiskt. Detta är en hårdvarubegränsning: videoprocessorn kan inte samtidigt betjäna två oberoende PiP-kanaler på grund av DMA- och videominnebegränsningar.
En annan viktig begränsning — varaktigheten av bakgrundsuppspelning. Om användaren inte interagerar med PiP-fönstret kan systemet pausa uppspelningen efter en tid för att spara energi. Automatisk paus av PiP på iOS inträffar efter 10–15 minuters inaktivitet, om appen inte har implementerat en keep-alive-mekanism via en bakgrundsuppgift. För videosamtal och streams rekommenderas att använda PushKit och VoIP-certifikat, som kringgår denna begränsning.
På Android implementeras PiP som ett inbyggt Activity-läge som aktiveras via metoden enterPictureInPictureMode. Från Android 8.0 (API 26) kan vilket Activity som helst växla till PiP-läge, och från Android 12 (API 31) har PiP-stöd för SurfaceView och TextureView dykt upp utan att behöva använda MediaCodec.
För PiP-stöd i Android-manifestet måste attributet android:supportsPictureInPicture anges för Activity i avsnittet
I Android har PiP-fönstret som standard inga kontrollelement. Utvecklaren kan lägga till anpassade åtgärder via RemoteAction i metoden setPictureInPictureParams. Upp till 3 åtgärder finns tillgängliga (till exempel: pausa/spela, spola bakåt/framåt, stäng). Varje åtgärd visas i systemets PiP-överlagring som en ikon. Till skillnad från iOS, där alla UI-element är strikt fixerade, ger Android större flexibilitet för grundläggande kontroller.
PiP på Android har olika möjligheter beroende på OS-version. På Android 8.0–8.1 är PiP endast tillgängligt för video som spelas upp via MediaPlayer eller MediaCodec med SurfaceView. Från Android 9 kan PictureInPictureArgs.Builder användas för att konfigurera PiP-fönstrets bildförhållande. Android 12 lade till PiP-stöd för anpassade SurfaceView och TextureView, samt förbättrad hantering av övergångar mellan helskärm och PiP-läge. Android 13+ gör det möjligt att visa PiP-fönstret även på låst skärm, om appen har lämplig behörighet.
| Android-version | PiP-möjligheter | API |
|---|---|---|
| 8.0–8.1 | Grundläggande PiP för MediaPlayer/MediaCodec | 26–27 |
| 9–11 | Konfiguration av bildförhållande, anpassade åtgärder | 28–30 |
| 12 | SurfaceView/TextureView-stöd i PiP | 31 |
| 13+ | PiP på låst skärm, förbättrade animationer | 33+ |
Den viktigaste skillnaden med Android PiP från iOS — möjligheten till multi-PiP. På Android från version 12 kan systemet visa flera PiP-fönster samtidigt, om apparna stöder det och enhetens prestanda tillåter. Men i praktiken begränsas multi-PiP av SoC:ens kapacitet: de flesta enheter stöder endast ett PiP-fönster på grund av avkodarens hårdvarubegränsningar, eftersom varje PiP-fönster kräver sin egen videoström och en separat avkodningssession.
Låt oss titta på praktisk implementering av PiP på båda mobilplattformarna med hänsyn till de senaste API-ändringarna.
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
) {
// Dölj UI-element, frigör minne
}
func pictureInPictureControllerDidStop(
_ pictureInPictureController: AVPictureInPictureController
) {
// Återställ UI, återuppta rendering
}
}
I exemplet initieras AVPictureInPictureController med playerLayer efter kontroll av isPictureInPictureSupported (PiP stöds inte på iPhone SE 1:a generationen och vissa iPads utan tillräckligt minne). Delegeraren meddelar appen om start och slut av PiP — i dessa callbacks måste UI-element döljas och återställas, eftersom appgränssnittet inte är synligt i PiP-läge. Vid övergång till PiP rekommenderas att stoppa alla animationer, dölja spelarens kontroller och frigöra oanvänt minne för att förhindra tvångsavlastning av appen från systemet.
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) {
// Dölj UI, fokusera endast på media
binding.controlsGroup.visibility = View.GONE
} else {
// Återställ UI
binding.controlsGroup.visibility = View.VISIBLE
}
}
}
Exemplet i Kotlin använder PictureInPictureParams.Builder för att konfigurera PiP. Metoden setAspectRatio ställer in PiP-fönstrets bildförhållande (16:9 för typisk video). setAutoEnterEnabled(true) aktiverar automatisk övergång till PiP när appen minimeras. Callbacken onPictureInPictureModeChanged anropas vid in- och utträde ur PiP — i den ska UI-element döljas eller visas. För video på SurfaceView krävs ytterligare konfigurationshantering genom att lägga till android:configChanges="screenSize|smallestScreenSize" i manifestet för att förhindra att Activity återskapas vid övergång till PiP-läge.
PiP är ett kraftfullt verktyg för att förbättra användarupplevelsen i appar där innehåll förblir relevant även när man växlar till andra uppgifter. Implementeringen av PiP måste dock vara motiverad och inte distrahera användaren.
Videosamtal och konferenser — ett av de främsta scenarierna för PiP. I Zoom, FaceTime, Google Meet gör PiP det möjligt att se samtalspartnern medan man arbetar i andra appar: läsa anteckningar, titta på en presentation eller kontrollera e-post. PiP för videosamtal kräver kamerasupport i bakgrunden och korrekt konfiguration av ljudsessionen för att fortsätta ljudinspelning i bakgrunden. På iOS används AVSampleBufferDisplayLayer istället för AVPlayerLayer för detta, eftersom videosamtal inte använder AVPlayer.
Streamingtjänster (YouTube, Netflix, Twitch) använder aktivt PiP för att fortsätta titta medan de söker efter nytt innehåll. YouTube Premium erbjuder PiP som en betalfunktion, Netflix begränsar också PiP till vissa abonnemang på grund av licensbegränsningar för innehåll. För att implementera PiP i en streaming-app krävs integration med DRM-system (FairPlay, Widevine) som stöder en säker pipeline i PiP-läge.
PiP är inte lämpligt för appar med interaktivt videoinnehåll där användarinteraktion krävs: utbildningsplattformar med tester i spelaren, spelströmmar med chatt, shoppingappar med produktlänkar i video. I dessa fall är PiP-fönstret för litet för att visa ytterligare information, och interaktiva element i PiP stöds inte av systemet. Rekommenderat att använda PiP endast för passivt tittande, när interaktion med innehåll inte krävs.
För musik- och podcastappar är PiP överflödigt — bakgrundsljud utan visuellt fönster räcker. PiP förbrukar extra GPU-resurser för att rendera video i ett flytande fönster, vilket förkortar batteritiden. Om innehållet är ljud (musik, podcaster, ljudböcker) — använd bakgrundsuppspelning utan PiP. Om det är visuellt — implementera PiP för att förbättra användarupplevelsen.
Vanliga frågor
PiP på iOS kräver iPhone 6s+, iOS 14+ och en region med stöd (USA, Kanada, Australien, EU, Ryssland och andra). För appen måste audio session konfigureras till kategorin .playback och UIBackgroundModes = audio läggas till. Kontrollera även inställningarna: Inställningar > Allmänt > Bild-i-bild.
På iOS bestäms storleken på PiP-fönstret helt av systemet och kan inte justeras av utvecklaren. På Android kan endast bildförhållandet ställas in via setAspectRatio i PictureInPictureParams.Builder, men den exakta fönsterstorleken bestäms av systemet. Användaren kan ändra storleken på PiP-fönstret på Android 12+ med en pinch-to-zoom-gest.
Ja, PiP fungerar med DRM-skyddat innehåll (FairPlay på iOS, Widevine L1 på Android) under förutsättning att DRM-sessionen stöder en säker pipeline i PiP-läge. Widevine L3 kanske inte stöder PiP eftersom det inte garanterar säkerheten för avkodat innehåll i ett flytande fönster. Kontrollera DRM-kompatibilitet med PiP i testfasen.
På iOS — endast ett PiP-fönster. På Android 12+ stöds multi-PiP teoretiskt, men i praktiken är de flesta enheter begränsade till ett fönster på grund av hårdvarubegränsningar. Toppenheter (Samsung Galaxy S24, Pixel 8) kan stödja 2 PiP-fönster, men med reducerad prestanda.
Ja, hantering av livscykeln är kritisk. På iOS får appen vid övergång till PiP meddelandet willStart där UI måste döljas och minne frigöras. På Android anropas onPictureInPictureModeChanged vid in-/utträde ur PiP. Vid felaktig livscykelhantering kan systemet avlasta appen från minnet och avbryta uppspelningen.
Sammanfattning
Vi utvecklar en mobil applikation nyckelfärdigt
IT Sectr skapar iOS- och Android-applikationer för startups och företag sedan 2017. Vi ger dig råd och föreslår den bästa lösningen.
Läs också