Android 8.0 (API düzeyi 26) sürümünden itibaren Android, etkinliklerin pencere içinde pencere (PIP) modunda başlatılmasına izin verir. Resim içinde resim, çoğunlukla video oynatma için kullanılan özel bir çok pencereli mod türüdür. Kullanıcının uygulamalar arasında gezinirken veya ana ekrandaki içeriklere göz atarken ekranın bir köşesine sabitlenmiş küçük bir pencerede video izlemesine olanak tanır.
PiP, sabitlenmiş video yer paylaşımı penceresi sağlamak için Android 7.0'da kullanıma sunulan çok pencereli API'lerden yararlanır. Uygulamanıza PiP eklemek için PiP'yi destekleyen etkinliklerinizi kaydetmeniz, etkinliğinizi gerektiğinde PiP moduna geçirmeniz ve etkinlik PiP modundayken kullanıcı arayüzü öğelerinin gizlendiğinden ve video oynatmanın devam ettiğinden emin olmanız gerekir.
PiP penceresi, ekranın en üst katmanında ve sistem tarafından seçilen bir köşede görünür.
PIP, Android 14 (API düzeyi 34) veya sonraki sürümleri çalıştıran uyumlu Android TV OS cihazlarda da desteklenir. Birçok benzerlik olsa da TV'de PiP kullanılırken dikkate alınması gereken ek noktalar vardır.
Kullanıcılar, PiP penceresiyle nasıl etkileşim kurabilir?
Kullanıcılar, PiP penceresini başka bir konuma sürükleyebilir. Android 12'den itibaren kullanıcılar şunları da yapabilir:
Tam ekran geçişi, kapatma düğmesi, ayarlar düğmesi ve uygulamanız tarafından sağlanan özel işlemleri (ör. oynatma kontrolleri) göstermek için pencereye tek dokunun.
Mevcut pencere içinde pencere boyutu ile maksimum veya minimum pencere içinde pencere boyutu arasında geçiş yapmak için pencereye iki kez dokunun. Örneğin, ekranı kaplayacak şekilde büyütülmüş bir pencereye iki kez dokunduğunuzda pencere simge durumuna küçülür. Bunun tersi de geçerlidir.
Pencereyi sol veya sağ kenara sürükleyerek saklayın. Pencereyi saklamadan çıkarmak için saklanan pencerenin görünen kısmına dokunun veya pencereyi dışarı sürükleyin.
İki parmağınızı kullanarak pencere içinde pencereyi yeniden boyutlandırın.
Uygulamanız, mevcut etkinliğin ne zaman PiP moduna gireceğini kontrol eder. Aşağıda bazı örnekler verilmiştir:
Kullanıcı ana sayfa düğmesine dokunduğunda veya ana sayfaya doğru yukarı kaydırdığında etkinlik, PiP moduna girebilir. Bu sayede Google Haritalar, kullanıcı aynı anda başka bir etkinlik yaparken yol tariflerini göstermeye devam eder.
Uygulamanız, kullanıcı videodan geri gelip diğer içeriklere göz atarken videoyu PiP moduna taşıyabilir.
Uygulamanız, kullanıcı bir içerik bölümünün sonunu izlerken videoyu PiP moduna geçirebilir. Ana ekranda, dizinin bir sonraki bölümüyle ilgili tanıtım veya özet bilgileri gösterilir.
Uygulamanız, kullanıcıların video izlerken ek içerikleri sıraya almasına olanak tanıyabilir. Ana ekranda içerik seçme etkinliği gösterilirken video, PiP modunda oynatılmaya devam eder.
PIP desteğini bildirme
Sistem, varsayılan olarak uygulamalarda PiP'yi otomatik olarak desteklemez. Uygulamanızda PiP'yi desteklemek istiyorsanız android:supportsPictureInPicture
değerini true
olarak ayarlayarak video etkinliğinizi manifest dosyanıza kaydedin. Ayrıca, etkinliğinizin düzen yapılandırması değişikliklerini işlediğini belirtin. Böylece, PiP modu geçişleri sırasında düzen değişiklikleri olduğunda etkinliğiniz yeniden başlatılmaz.
<activity android:name="VideoActivity"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...
Etkinliğinizi PIP'e geçirme
Android 12'den itibaren, setAutoEnterEnabled
işaretini true
olarak ayarlayarak etkinliğinizi PiP moduna geçirebilirsiniz. Bu ayarla, bir etkinlik onUserLeaveHint
içinde enterPictureInPictureMode()
açıkça çağrılmadan gerektiğinde otomatik olarak PiP moduna geçer. Ayrıca bu özellik, geçişlerin çok daha sorunsuz olmasını sağlar. Ayrıntılar için Hareketle gezinme özelliğini kullanırken resim içinde resim moduna geçişi daha sorunsuz hale getirme başlıklı makaleyi inceleyin.
Android 11 veya önceki sürümleri hedefliyorsanız PiP moduna geçmek için bir etkinliğin enterPictureInPictureMode()
çağrısı yapması gerekir. Örneğin, aşağıdaki kod, kullanıcı uygulamanın kullanıcı arayüzünde özel bir düğmeyi tıkladığında etkinliği PiP moduna geçirir:
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; } ... }
Bir etkinliği arka plana göndermek yerine PiP moduna geçiren bir mantık eklemek isteyebilirsiniz. Örneğin, Google Haritalar, uygulama gezinirken kullanıcı ana sayfa veya son uygulamalar düğmesine basarsa PIP moduna geçer. onUserLeaveHint()
'ı geçersiz kılarak bu durumu yakalayabilirsiniz:
Kotlin
override fun onUserLeaveHint() { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode() } }
Java
@Override public void onUserLeaveHint () { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode(); } }
Önerilen: Kullanıcılara sorunsuz bir PiP geçiş deneyimi sunun
Android 12, tam ekran ve PiP pencereleri arasındaki animasyonlu geçişlerde önemli görünüm iyileştirmeleri yaptı. Geçerli tüm değişiklikleri uygulamanızı önemle tavsiye ederiz. Bu değişiklikleri uyguladığınızda, katlanabilir cihazlar ve tabletler gibi büyük ekranlarda başka bir işlem yapmanıza gerek kalmadan otomatik olarak ölçeklendirilir.
Uygulamanızda geçerli güncellemeler yoksa PIP geçişleri yine de çalışır ancak animasyonlar daha az gelişmiş olur. Örneğin, tam ekrandan resim içinde resim moduna geçiş, geçiş tamamlanana kadar resim içinde resim penceresinin kaybolmasına neden olabilir.
Bu değişiklikler aşağıdakileri içerir.
- Hareketle gezinme özelliğini kullanırken PIP moduna geçişi daha sorunsuz hale getirme
- PiP moduna girme ve çıkma için uygun bir
sourceRectHint
ayarlama - Video olmayan içeriklerde sorunsuz yeniden boyutlandırmayı devre dışı bırakma
Sorunsuz bir geçiş deneyimi sağlamak için Android Kotlin PictureInPicture örneğini referans olarak kullanın.
Hareketle gezinme özelliğini kullanarak PIP moduna daha sorunsuz geçiş yapma
Android 12'den itibaren setAutoEnterEnabled
işareti, hareketle gezinme kullanılarak PiP modunda video içeriğine geçiş için çok daha akıcı bir animasyon sağlar. Örneğin, tam ekrandan ana sayfaya yukarı kaydırırken bu işareti kullanabilirsiniz.
Bu değişikliği yapmak için aşağıdaki adımları tamamlayın ve referans olarak bu örneğe bakın:
PictureInPictureParams.Builder
oluşturmak içinsetAutoEnterEnabled
kullanın:Kotlin
setPictureInPictureParams(PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) .setSourceRectHint(sourceRectHint) .setAutoEnterEnabled(true) .build())
Java
setPictureInPictureParams(new PictureInPictureParams.Builder() .setAspectRatio(aspectRatio) .setSourceRectHint(sourceRectHint) .setAutoEnterEnabled(true) .build());
setPictureInPictureParams
'ı güncelPictureInPictureParams
ile erken arayın. Uygulama, Android 11'de olduğu gibionUserLeaveHint
geri çağırma yönteminin tamamlanmasını beklemez.Örneğin, en boy oranı değişirse
setPictureInPictureParams
işlevini ilk oynatma ve sonraki oynatmalarda çağırmak isteyebilirsiniz.setAutoEnterEnabled(false)
işlevini yalnızca gerektiğinde kullanın. Örneğin, mevcut oynatma duraklatılmış durumdaysa PIP moduna girmek istemeyebilirsiniz.
Küçük resim moduna girme ve çıkma için uygun bir sourceRectHint
ayarlayın.
Android 8.0'da PiP'nin kullanıma sunulmasıyla birlikte setSourceRectHint
, resim içinde resim moduna geçişin ardından görünür olan etkinliğin alanını (ör. video oynatıcıdaki video görünümü sınırları) belirtiyordu.
Android 12'de sistem, pencere içinde pencere moduna girerken ve çıkarken çok daha akıcı bir animasyon uygulamak için sourceRectHint
kullanır.
PiP moduna girme ve çıkma için sourceRectHint
simgesini doğru şekilde ayarlamak üzere:
PictureInPictureParams
öğesinisourceRectHint
olarak uygun sınırlara göre oluşturun. Ayrıca video oynatıcıya bir düzen değişikliği dinleyicisi eklemenizi öneririz: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);
Gerekirse sistem çıkış geçişine başlamadan önce
sourceRectHint
öğesini güncelleyin. Sistem PiP modundan çıkmak üzereyken etkinliğin görünüm hiyerarşisi hedef yapılandırmasına (örneğin, tam ekran) göre düzenlenir. Uygulama, etkinliği algılamak ve animasyon başlamadan öncesourceRectHint
öğesini güncellemek için kök görünümüne veya hedef görünümüne (ör. video oynatıcı görünümü) bir düzen değişikliği işleyici ekleyebilir.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()); } });
Video olmayan içeriklerde sorunsuz yeniden boyutlandırmayı devre dışı bırakma
Android 12'de, PiP penceresinde video olmayan içeriklerin boyutu yeniden ayarlanırken çok daha akıcı bir geçiş animasyonu sağlayan setSeamlessResizeEnabled
işareti ekleniyor. Daha önce, PiP penceresinde video olmayan içeriklerin yeniden boyutlandırılması, rahatsız edici görsel öğelere neden olabiliyordu.
Video içeriğinin sorunsuz şekilde yeniden boyutlandırılmasını sağlamak için:
Kotlin
setPictureInPictureParams(PictureInPictureParams.Builder() .setSeamlessResizeEnabled(true) .build())
Java
setPictureInPictureParams(new PictureInPictureParams.Builder() .setSeamlessResizeEnabled(true) .build());
PiP sırasında kullanıcı arayüzünü kullanma
Etkinlik, pencere içinde pencere (PiP) moduna girdiğinde veya bu moddan çıktığında sistem Activity.onPictureInPictureModeChanged()
ya da Fragment.onPictureInPictureModeChanged()
işlevini çağırır.
Android 15, PIP moduna girerken daha sorunsuz bir geçiş sağlayan değişiklikler sunuyor. Bu, ana kullanıcı arayüzünün üzerine yerleştirilmiş kullanıcı arayüzü öğeleri olan ve PiP'ye giren uygulamalar için faydalıdır.
Geliştiriciler, yer paylaşımlı kullanıcı arayüzü öğelerinin görünürlüğünü değiştiren mantığı tanımlamak için onPictureInPictureModeChanged()
geri çağırmasını kullanır.
Bu geri çağırma, PiP giriş veya çıkış animasyonu tamamlandığında tetiklenir.
Android 15'ten itibaren PictureInPictureUiState
sınıfı yeni bir durum içerir.
Bu yeni kullanıcı arayüzü durumuyla birlikte, Android 15'i hedefleyen uygulamalar, PIP animasyonu başlar başlamaz Activity#onPictureInPictureUiStateChanged()
geri çağırmasının isTransitioningToPip()
ile çağrıldığını gözlemler.
Uygulama PiP modundayken alakalı olmayan birçok kullanıcı arayüzü öğesi vardır. Örneğin, öneriler, yaklaşan videolar, puanlar ve başlıklar gibi bilgileri içeren görünümler veya düzenler. Uygulama PiP moduna geçtiğinde, bu kullanıcı arayüzü öğelerini gizlemek için onPictureInPictureUiStateChanged()
geri aramasını kullanın.
Uygulama, PiP penceresinden tam ekran moduna geçtiğinde aşağıdaki örneklerde gösterildiği gibi bu öğeleri göstermek için onPictureInPictureModeChanged()
geri çağırmasını kullanın:
Kotlin
override fun onPictureInPictureUiStateChanged(pipState: PictureInPictureUiState) { if (pipState.isTransitioningToPip()) { // Hide UI elements. } }
Java
@Override public void onPictureInPictureUiStateChanged(PictureInPictureUiState pipState) { if (pipState.isTransitioningToPip()) { // Hide UI elements. } }
Kotlin
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean) { if (isInPictureInPictureMode) { // Unhide UI elements. } }
Java
@Override public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { if (isInPictureInPictureMode) { // Unhide UI elements. } }
Alakasız kullanıcı arayüzü öğelerinin (PiP penceresi için) bu hızlı görünürlük açma/kapatma işlemi, daha sorunsuz ve titreşimsiz bir PiP giriş animasyonu sağlar.
Etkinliğin kullanıcı arayüzü öğelerini yeniden çizmek için bu geri çağırmaları geçersiz kılın. Etkinliğinizin, resim içinde resim modunda küçük bir pencerede gösterileceğini unutmayın. Uygulama PiP modundayken kullanıcılar uygulamanızın kullanıcı arayüzü öğeleriyle etkileşimde bulunamıyor ve küçük kullanıcı arayüzü öğelerinin ayrıntılarını görmek zor olabiliyor. Minimum kullanıcı arayüzüyle video oynatma etkinlikleri en iyi kullanıcı deneyimini sağlar.
Uygulamanızın PiP için özel işlemler sağlaması gerekiyorsa bu sayfadaki Kontrol ekleme bölümüne bakın. Etkinliğiniz PiP'ye girmeden önce diğer kullanıcı arayüzü öğelerini kaldırın ve etkinliğiniz tekrar tam ekran olduğunda bunları geri yükleyin.
Kontrol ekle
PiP penceresi, kullanıcı pencerenin menüsünü açtığında (mobil cihazda pencereye dokunarak veya TV kumandasından menüyü seçerek) kontrolleri gösterebilir.
Bir uygulamanın etkin bir medya oturumu varsa oynatma, duraklatma, sonraki ve önceki kontrolleri gösterilir.
Ayrıca, PiP moduna girmeden önce PictureInPictureParams
ile PictureInPictureParams.Builder.setActions()
oluşturarak özel işlemleri açıkça belirtebilir ve PiP moduna girdiğinizde enterPictureInPictureMode(android.app.PictureInPictureParams)
veya setPictureInPictureParams(android.app.PictureInPictureParams)
kullanarak parametreleri iletebilirsiniz.
Dikkatli olun. getMaxNumPictureInPictureActions()
'dan fazla eklemeye çalışırsanız yalnızca maksimum sayıya ulaşırsınız.
PiP modundayken video oynatmaya devam etme
Etkinliğiniz PiP'ye geçtiğinde sistem, etkinliği duraklatılmış duruma getirir ve etkinliğin onPause()
yöntemini çağırır. Etkinlik PiP moduna geçiş sırasında duraklatılırsa video oynatma duraklatılmamalı ve oynatmaya devam etmelidir.
Android 7.0 ve sonraki sürümlerde, sistem etkinliğinizin onStop()
ve onStart()
yöntemlerini çağırdığında video oynatmayı duraklatıp devam ettirmeniz gerekir. Bu sayede, uygulamanızın onPause()
içinde PiP modunda olup olmadığını kontrol etmeniz ve oynatmaya açıkça devam etmeniz gerekmez.
setAutoEnterEnabled
işaretini true
olarak ayarlamadıysanız ve onPause()
uygulamanızda oynatmayı duraklatmanız gerekiyorsa isInPictureInPictureMode()
işlevini çağırarak PiP modunu kontrol edin ve oynatmayı uygun şekilde yönetin. Örneğin:
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. ... } }
Etkinliğiniz PIP modundan tam ekran moduna geri döndüğünde sistem, etkinliğinize devam eder ve onResume()
yönteminizi çağırır.
PiP için tek bir oynatma etkinliği kullanma
Uygulamanızda, kullanıcılar ana ekranda içeriklere göz atarken pencere içinde pencere modunda video oynatma etkinliği devam ederken yeni bir video seçebilir. Kullanıcıyı şaşırtabilecek yeni bir etkinlik başlatmak yerine, yeni videoyu mevcut oynatma etkinliğinde tam ekran modunda oynatın.
Video oynatma istekleri için tek bir etkinliğin kullanılmasını ve gerektiğinde PiP moduna geçilmesini veya PiP modundan çıkılmasını sağlamak için etkinliğin android:launchMode
özelliğini manifestinizde singleTask
olarak ayarlayın:
<activity android:name="VideoActivity"
...
android:supportsPictureInPicture="true"
android:launchMode="singleTask"
...
Etkinliğinizde, onNewIntent()
ile geçersiz kılın ve gerekirse mevcut video oynatmayı durdurarak yeni videoyu işleyin.
En iyi uygulamalar
PiP, RAM'i düşük olan cihazlarda devre dışı bırakılabilir. Uygulamanız PIP'yi kullanmadan önce hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
işlevini çağırarak bu özelliğin kullanılabilir olduğundan emin olun.
PIP, tam ekran video oynatılan etkinlikler için tasarlanmıştır. Etkinliğinizi PiP moduna geçirirken video içeriği dışında bir şey göstermeyin. Etkinliğinizin ne zaman PiP moduna girdiğini takip edin ve PiP sırasında kullanıcı arayüzünü yönetme bölümünde açıklandığı gibi kullanıcı arayüzü öğelerini gizleyin.
Bir etkinlik PiP modundayken varsayılan olarak giriş odağı almaz. PIP modundayken giriş etkinliklerini almak için MediaSession.setCallback()
simgesini kullanın.
setCallback()
simgesini kullanma hakkında daha fazla bilgi için Ne çalıyor kartını görüntüleme başlıklı makaleyi inceleyin.
Uygulamanız PiP modundayken PiP penceresinde video oynatılması, müzik çalar uygulaması veya sesli arama uygulaması gibi başka bir uygulamada ses parazitine neden olabilir. Bunu önlemek için videoyu oynatmaya başladığınızda ses odağı isteyin ve Ses Odağını Yönetme bölümünde açıklandığı gibi ses odağı değişikliği bildirimlerini işleyin. PiP modundayken ses odağı kaybı bildirimi alırsanız video oynatmayı duraklatın veya sonlandırın.
Uygulamanız pencere içinde pencere moduna girmek üzereyken yalnızca üstteki etkinliğin pencere içinde pencere moduna girdiğini unutmayın. Çok pencereli cihazlar gibi bazı durumlarda aşağıdaki etkinlik artık gösterilebilir ve PiP etkinliğinin yanında tekrar görünür hale gelebilir. Bu durumu uygun şekilde ele almanız gerekir. Aşağıdaki etkinliğin onResume()
veya onPause()
geri çağırma alması da buna dahildir. Kullanıcının etkinlikle etkileşime geçmesi de mümkündür. Örneğin, bir video listesi etkinliği görüntüleniyorsa ve oynatılan video etkinliği küçük resim modundaysa kullanıcı listeden yeni bir video seçebilir ve küçük resim etkinliği buna göre güncellenmelidir.
Ek örnek kod
Kotlin ile yazılmış örnek bir uygulamayı indirmek için Android PictureInPicture Sample (Kotlin) başlıklı makaleyi inceleyin.