Picture-in-Picture (PiP) è una modalità di riproduzione video che mostra il contenuto in una finestra fluttuante sopra le altre applicazioni, consentendo all’utente di continuare a guardare mentre riduce a icona l’app o passa da un programma all’altro. La finestra PiP si posiziona automaticamente in un angolo dello schermo e può essere spostata dall’utente. Secondo la documentazione Apple AVPictureInPictureController (2026), la modalità PiP è supportata su iOS a partire dalla versione 14 e su Android a partire dalla versione 8.0.
Punti chiave
Picture-in-Picture (PiP) è una modalità di visualizzazione video che mostra il contenuto in una piccola finestra fluttuante che rimane sopra tutte le altre finestre e applicazioni. L’utente può spostare la finestra PiP sullo schermo, ridimensionarla (su alcune piattaforme) e continuare a guardare il contenuto mentre lavora in altre applicazioni.
Il concetto di PiP proviene dalla televisione: già negli anni ’90, i televisori permettevano di mostrare un secondo canale in un angolo dello schermo. Sui dispositivi mobili, PiP è apparso per la prima volta su iPad con iOS 9 (2015) per i video in Safari, mentre il PiP di sistema completo per le app è diventato disponibile in iOS 14 (2020). Il supporto PiP su Android è arrivato prima — nella versione 8.0 Oreo (2017), ma solo per i video, e da Android 12 per tutti i tipi di contenuto.
PiP si differenzia dalla riproduzione in background perché il video continua a essere visualizzato sullo schermo, non solo riprodotto nel flusso audio. La riproduzione audio in background è disponibile su entrambe le piattaforme, ma PiP offre all’utente un controllo visivo sul contenuto: può vedere i fotogrammi, mettere in pausa, riavvolgere o chiudere la finestra. Questo è particolarmente importante per tutorial video, streaming e videochiamate, dove il contenuto visivo è importante quanto l’audio.
Architetturalmente, PiP è implementato tramite un gestore di finestre di sistema che crea una finestra separata con priorità di visualizzazione ridotta. L’app delega l’output video a un servizio di sistema che continua a renderizzare il video anche dopo che l’app passa in background o viene ridotta a icona.
Il processo inizia quando l’utente riduce a icona l’app con video attivo o preme il pulsante PiP (su iOS), oppure il sistema trasferisce automaticamente l’Activity in modalità PiP (su Android). Il gestore di finestre di sistema cattura il flusso video e crea una finestra fluttuante con proporzioni fisse. La dimensione della finestra dipende dal rapporto d’aspetto del video originale e dai vincoli della piattaforma: su iOS, la finestra PiP occupa circa 1/6–1/4 della larghezza dello schermo; su Android, non meno di 108 dp di larghezza e 240 dp di altezza per i dispositivi mobili.
Quando la finestra PiP è attiva, l’app può trovarsi in uno di tre stati: in background (ridotta a icona), nello stato attivo (l’utente è tornato all’app), o in attesa (il sistema ha messo in pausa PiP per mancanza di risorse). Durante la transizione a PiP, l’app dovrebbe sospendere le operazioni UI non necessarie (animazioni, rendering dell’interfaccia) e liberare memoria, poiché le risorse di sistema sono allocate più strettamente in modalità multitasking. iOS invia automaticamente all’app una notifica AVPictureInPictureControllerWillStartNotification, mentre Android invia il callback onPictureInPictureModeChanged.
La finestra PiP ha limitazioni significative: non può visualizzare elementi di controllo UI standard (pulsante pausa, barra di avanzamento) — solo una sovrapposizione minima di sistema con controlli di base: play/pausa, chiudi, espandi a schermo intero. L’interfaccia PiP di sistema su iOS include pulsanti pausa e chiusura, mentre su Android include gli stessi elementi più un pulsante aggiuntivo per le impostazioni. L’interazione con il contenuto all’interno di PiP (riavvolgimento, selezione sottotitoli) non è possibile — per farlo, bisogna espandere l’app a schermo intero.
Su iOS, PiP è implementato tramite il framework AVKit e la classe AVPictureInPictureController. Questa API è disponibile su iOS 14+ per iPhone e iPad, ma con requisiti diversi: su iPad, PiP funziona tramite AVPlayerLayer; su iPhone, solo tramite AVPlayerViewController.
Affinché PiP funzioni su iOS, devono essere soddisfatte diverse condizioni: l’app deve usare AVPlayer per la riproduzione video, la sessione audio deve essere impostata sulla categoria .playback o .playAndRecord, e l’app deve avere entitlements per l’audio in background (UIBackgroundModes = audio). Senza queste impostazioni, PiP non si avvierà — il sistema rifiuterà la richiesta di sessione PiP perché non può garantire una riproduzione corretta dopo il passaggio in background.
Su iOS, la finestra PiP appare automaticamente quando si riduce a icona l’app se il video è attivamente in riproduzione e l’utente non ha disattivato questa funzione nelle impostazioni. L’utente può anche ridurre manualmente il video in PiP tramite il pulsante in AVPlayerViewController. La dimensione della finestra PiP su iOS è fissa e determinata dal sistema — lo sviluppatore non può modificarla. Il rapporto d’aspetto della finestra PiP corrisponde a quello del video originale, ma la dimensione massima è limitata a 1/4 della larghezza dello schermo su iPhone e 1/3 su iPad.
Le principali limitazioni di PiP su iOS: impossibilità di UI personalizzata nella finestra PiP, un solo flusso PiP alla volta e necessità di un AVPlayer attivo per il funzionamento di PiP. Il multi-PiP — riproduzione simultanea di più finestre PiP — non è supportato su iOS. Se si tenta di avviare un secondo PiP, il primo viene automaticamente chiuso. Questa è una limitazione hardware: il processore video non può gestire contemporaneamente due canali PiP indipendenti a causa dei vincoli di DMA e memoria video.
Un’altra limitazione importante è la durata della riproduzione in background. Se l’utente non interagisce con la finestra PiP, il sistema potrebbe mettere in pausa la riproduzione dopo un po’ di tempo per risparmiare energia. La pausa automatica di PiP su iOS avviene dopo 10–15 minuti di inattività se l’app non ha implementato un meccanismo keep-alive tramite un’attività in background. Per videochiamate e streaming, si consiglia di utilizzare PushKit e certificati VoIP, che aggirano questa limitazione.
Su Android, PiP è implementato come modalità Activity integrata che si attiva tramite il metodo enterPictureInPictureMode. Da Android 8.0 (API 26), qualsiasi Activity può entrare in modalità PiP, e da Android 12 (API 31) è disponibile il supporto PiP per SurfaceView e TextureView senza utilizzare MediaCodec.
Per supportare PiP nel manifest di Android, l’attributo android:supportsPictureInPicture deve essere specificato per l’Activity nella sezione
In Android, la finestra PiP per impostazione predefinita non ha elementi di controllo. Lo sviluppatore può aggiungere azioni personalizzate tramite RemoteAction nel metodo setPictureInPictureParams. Sono disponibili fino a 3 azioni (ad esempio: pausa/play, riavvolgimento indietro/avanti, chiusura). Ogni azione appare nella sovrapposizione di sistema PiP come icona. A differenza di iOS, dove tutti gli elementi UI sono strettamente fissi, Android offre maggiore flessibilità per i controlli di base.
PiP su Android ha capacità diverse a seconda della versione del sistema operativo. Su Android 8.0–8.1, PiP è disponibile solo per video riprodotti tramite MediaPlayer o MediaCodec con SurfaceView. Da Android 9 è possibile utilizzare PictureInPictureArgs.Builder per configurare il rapporto d’aspetto della finestra PiP. Android 12 ha aggiunto il supporto PiP per SurfaceView e TextureView personalizzati, oltre a transizioni migliorate tra la modalità a schermo intero e PiP. Android 13+ consente di visualizzare la finestra PiP anche con lo schermo bloccato, se l’app dispone dell’autorizzazione appropriata.
| Versione Android | Capacità PiP | API |
|---|---|---|
| 8.0–8.1 | PiP di base per MediaPlayer/MediaCodec | 26–27 |
| 9–11 | Configurazione rapporto d’aspetto, azioni personalizzate | 28–30 |
| 12 | Supporto PiP per SurfaceView/TextureView | 31 |
| 13+ | PiP su schermo bloccato, animazioni migliorate | 33+ |
Una differenza chiave di PiP su Android rispetto a iOS è la capacità multi-PiP. Su Android 12+, il sistema può mostrare più finestre PiP contemporaneamente se le app lo supportano e le prestazioni del dispositivo lo consentono. Tuttavia, in pratica, il multi-PiP è limitato dalle capacità del SoC: la maggior parte dei dispositivi supporta solo una finestra PiP a causa delle limitazioni hardware del decoder, poiché ogni finestra PiP richiede il proprio flusso video e una sessione di decodifica separata.
Vediamo un’implementazione pratica di PiP su entrambe le piattaforme mobili, tenendo conto delle ultime modifiche API.
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
) {
// Nascondere elementi UI, liberare memoria
}
func pictureInPictureControllerDidStop(
_ pictureInPictureController: AVPictureInPictureController
) {
// Ripristinare UI, riprendere rendering
}
}
In questo esempio, AVPictureInPictureController viene inizializzato con playerLayer dopo aver verificato isPictureInPictureSupported (PiP non è supportato su iPhone SE 1ª generazione e alcuni iPad senza memoria sufficiente). Il delegato notifica all’app l’inizio e la fine di PiP — in questi callback gli elementi UI devono essere nascosti e ripristinati, poiché l’interfaccia dell’app non è visibile in modalità PiP. Durante la transizione a PiP, si consiglia di fermare tutte le animazioni, nascondere i controlli del player e liberare la memoria inutilizzata per evitare che il sistema scarichi forzatamente l’app.
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) {
// Nascondere UI, concentrarsi solo sui media
binding.controlsGroup.visibility = View.GONE
} else {
// Ripristinare UI
binding.controlsGroup.visibility = View.VISIBLE
}
}
}
L’esempio in Kotlin utilizza PictureInPictureParams.Builder per configurare PiP. Il metodo setAspectRatio imposta il rapporto d’aspetto della finestra PiP (16:9 per un video tipico). setAutoEnterEnabled(true) abilita la transizione automatica a PiP quando si riduce a icona l’app. Il callback onPictureInPictureModeChanged viene invocato all’ingresso e all’uscita da PiP — qui gli elementi UI devono essere nascosti o mostrati. Per il video su SurfaceView, è necessaria un’ulteriore gestione della configurazione aggiungendo android:configChanges="screenSize|smallestScreenSize" al manifest per evitare la ricreazione dell’Activity durante la transizione alla modalità PiP.
PiP è uno strumento potente per migliorare l’esperienza utente nelle app in cui il contenuto rimane rilevante anche quando si passa ad altre attività. Tuttavia, l’implementazione di PiP deve essere giustificata e non distrarre l’utente.
Le videochiamate e le conferenze sono uno degli scenari principali di PiP. In Zoom, FaceTime, Google Meet, PiP permette di vedere l’interlocutore mentre si lavora in altre app: leggere appunti, guardare una presentazione o controllare la posta elettronica. Il PiP per le videochiamate richiede il supporto della fotocamera in background e una corretta configurazione della sessione audio per continuare la cattura audio in background. Su iOS, questo viene fatto utilizzando AVSampleBufferDisplayLayer invece di AVPlayerLayer, poiché le videochiamate non utilizzano AVPlayer.
I servizi di streaming (YouTube, Netflix, Twitch) utilizzano attivamente PiP per continuare la visione durante la ricerca di nuovi contenuti. YouTube Premium offre PiP come funzionalità a pagamento, e Netflix limita PiP a determinati piani di abbonamento a causa delle restrizioni di licenza dei contenuti. Per implementare PiP in un’app di streaming, è necessaria l’integrazione con un sistema DRM (FairPlay, Widevine) che supporti una pipeline sicura in modalità PiP.
PiP non è adatto per app con contenuti video interattivi che richiedono l’interazione dell’utente: piattaforme educative con test all’interno del player, streaming di giochi con chat, app per acquisti con collegamenti a prodotti nel video. In questi casi, la finestra PiP è troppo piccola per visualizzare informazioni aggiuntive e gli elementi interattivi non sono supportati all’interno di PiP. Si consiglia di utilizzare PiP solo per la visione passiva, quando non è richiesta interazione con il contenuto.
Per le app musicali e di podcast, PiP è eccessivo — l’audio in background senza finestra visiva è sufficiente. PiP consuma risorse GPU aggiuntive per il rendering video in una finestra fluttuante, riducendo la durata della batteria. Se il contenuto è audio (musica, podcast, audiolibri) — utilizzare la riproduzione in background senza PiP. Se è visivo — implementare PiP per migliorare l’esperienza utente.
Domande frequenti
PiP su iOS richiede iPhone 6s+, iOS 14+ e una regione supportata (USA, Canada, Australia, UE, Russia e altri). L’app deve configurare la sessione audio sulla categoria .playback e aggiungere UIBackgroundModes = audio. Controllare anche le impostazioni: Impostazioni > Generali > Picture in Picture.
Su iOS, la dimensione della finestra PiP è interamente determinata dal sistema e non può essere configurata dallo sviluppatore. Su Android, è possibile impostare solo il rapporto d’aspetto tramite setAspectRatio in PictureInPictureParams.Builder, ma la dimensione esatta della finestra è determinata dal sistema. L’utente può ridimensionare la finestra PiP su Android 12+ con il gesto di pinch-to-zoom.
Sì, PiP funziona con contenuti protetti da DRM (FairPlay su iOS, Widevine L1 su Android) a condizione che la sessione DRM supporti una pipeline sicura in modalità PiP. Widevine L3 potrebbe non supportare PiP, poiché non garantisce la sicurezza del contenuto decodificato in una finestra fluttuante. Verificare la compatibilità DRM con PiP durante la fase di test.
Su iOS — una sola finestra PiP. Su Android 12+, teoricamente il multi-PiP è supportato, ma in pratica la maggior parte dei dispositivi è limitata a una finestra a causa di vincoli hardware. I dispositivi di punta (Samsung Galaxy S24, Pixel 8) possono supportare 2 finestre PiP, ma con prestazioni ridotte.
Sì, la gestione del ciclo di vita è criticamente importante. Su iOS, durante la transizione a PiP, l’app riceve una notifica willStart in cui l’interfaccia deve essere nascosta e la memoria liberata. Su Android, onPictureInPictureModeChanged viene chiamato all’ingresso/uscita da PiP. Senza una corretta gestione del ciclo di vita, il sistema potrebbe scaricare l’app dalla memoria, interrompendo la riproduzione.
Riepilogo
Svilupperemo un'applicazione mobile chiavi in mano
IT Sectr crea applicazioni iOS e Android per startup e aziende dal 2017. Ti consulteremo e ti proporremo la soluzione migliore.
Leggi anche