Android 8.0 (API düzeyi 26) sürümünden başlayarak, etkinliklerin pencere içinde pencere (PIP) modunda başlatılmasına izin verir. PiP, çoğunlukla video oynatma için kullanılan özel bir çoklu pencere modu türüdür. Kullanıcının uygulamalar arasında gezinirken veya ana ekranda içeriklere göz atarken ekranın köşesine sabitlenmiş küçük bir pencerede video izlemesini sağlar.
PiP, sabitlenmiş video yer paylaşımlı penceresi sağlamak için Android 7.0'da kullanıma sunulan çoklu pencere API'lerinden yararlanır. Uygulamanıza PiP eklemek için PiP'yi destekleyen etkinliklerinizi kaydetmeniz, gerektiği şekilde etkinliğinizi 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, sistem tarafından seçilen bir köşede görüntülenir.
Kullanıcılar PiP penceresiyle nasıl etkileşim kurabilir?
Kullanıcılar PiP penceresini başka bir konuma sürükleyebilirler. Android 12'den itibaren kullanıcılar şunları da yapabilirler:
Tam ekran açma/kapatma düğmesi, kapatma düğmesi, ayarlar düğmesi ve uygulamanız tarafından sağlanan özel işlemleri (ör. oynatma kontrolleri) görüntülemek için pencereye bir kez dokunun.
Mevcut PiP boyutu ile maksimum veya minimum PiP boyutu arasında geçiş yapmak için pencereye iki kez dokunun. Örneğin, ekranı kaplayan bir pencereye iki kez dokunduğunuzda boyut küçültülür. Tam tersi de doğrudur.
Pencereyi sol veya sağ kenara sürükleyerek saklayın. Pencereyi açmak için saklanmış pencerenin görünür bölümüne dokunun veya dışarı sürükleyin.
Yakınlaştırmak için sıkıştırma özelliğini kullanarak PiP penceresini yeniden boyutlandırın.
Uygulamanız, mevcut etkinliğin PiP moduna ne zaman gireceğini kontrol eder. Bazı örnekler:
Bir etkinlik, kullanıcı ana sayfa düğmesine dokunduğunda veya ana sayfa düğmesine gittiğinde PIP moduna girebilir. Kullanıcı aynı anda başka bir etkinlik çalıştırırken Google Haritalar yol tariflerini görüntülemeye bu şekilde devam eder.
Kullanıcı diğer içeriklere göz atmak için videodan geri döndüğünde uygulamanız videoyu PiP moduna taşıyabilir.
Kullanıcılar bir bölümün sonunu izlerken uygulamanız videoyu PiP moduna geçirebilir. Ana ekranda, dizinin bir sonraki bölümü ile ilgili tanıtım veya özet bilgiler görüntülenir.
Uygulamanız, kullanıcıların video izlerken ek içerikleri sıraya almaları için bir yol sağlayabilir. Ana ekranda bir içerik seçimi etkinliği görüntülenirken video, PiP modunda oynatılmaya devam eder.
PiP desteği beyan etme
Varsayılan olarak sistem, uygulamalar için PiP'yi otomatik olarak desteklemez. Uygulamanızda PiP'nin desteklenmesini istiyorsanız android:supportsPictureInPicture
değerini true
olarak ayarlayarak video etkinliğinizi manifest dosyanıza kaydedin. Ayrıca, PiP modu geçişleri sırasında düzen değişikliği olduğunda etkinliğinizin yeniden başlatılmaması için etkinliğinizin düzen yapılandırma değişikliklerini işlemesini de belirtin.
<activity android:name="VideoActivity"
android:supportsPictureInPicture="true"
android:configChanges=
"screenSize|smallestScreenSize|screenLayout|orientation"
...
Etkinliğinizi PiP olarak değiştirin
Android 12 sürümünden itibaren setAutoEnterEnabled
işaretini true
olarak ayarlayarak etkinliğinizi PiP moduna geçirebilirsiniz. Bu ayar kullanıldığında, etkinlikler onUserLeaveHint
'te açıkça enterPictureInPictureMode()
çağrısı yapmak zorunda kalmadan otomatik olarak PiP moduna geçer. Bu da daha yumuşak geçişler
sağlayarak ek fayda sağlar. Ayrıntılar için Hareketle gezinmeden PiP moduna geçişleri daha sorunsuz hale getirme başlıklı makaleye bakın.
Android 11 veya önceki sürümleri hedefliyorsanız PiP moduna geçmek için bir etkinlik enterPictureInPictureMode()
kodunu çağırmalıdır. Örneğin, aşağıdaki kod, kullanıcı uygulamanın kullanıcı arayüzündeki ö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 gitmek yerine PiP moduna geçiren bir mantık eklemek isteyebilirsiniz. Örneğin, kullanıcı uygulama gezinirken ana sayfa veya son kullanılanlar düğmesine basarsa
PIP moduna geçer. Bu destek kaydını, onUserLeaveHint()
değerini geçersiz kılarak tespit edebilirsiniz:
Kotlin
override fun onUserLeaveHint() { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode() } }
Java
@Override public void onUserLeaveHint () { if (iWantToBeInPipModeNow()) { enterPictureInPictureMode(); } }
Öneri: Kullanıcılara şık bir PiP geçiş deneyimi sunun
Android 12, tam ekran ve PiP pencereler arasındaki animasyonlu geçişlerde önemli kozmetik iyileştirmeler ekledi. Tüm geçerli değişiklikleri uygulamanızı önemle tavsiye ederiz. Bunu yaptıktan sonra, bu değişiklikler başka bir işlem gerekmeden katlanabilir cihazlar ve tabletler gibi büyük ekranlar için otomatik olarak ölçeklendirilir.
Uygulamanız geçerli güncellemeler içermiyorsa PiP geçişleri çalışmaya devam eder ancak animasyonlar daha az gösterişlidir. Örneğin, tam ekrandan PiP moduna geçiş, geçiş işlemi tamamlandığında PiP penceresinin yeniden gösterilmeden önce geçiş sırasında kaybolmasına neden olabilir.
Bu değişiklikler aşağıdakileri içerir.
- Hareketle gezinmeden PiP moduna daha rahat geçiş
- PiP moduna girmek ve bu moddan çıkmak için uygun bir
sourceRectHint
ayarlama - Video olmayan içerikler için sorunsuz yeniden boyutlandırmayı devre dışı bırakma
Kaliteli bir geçiş deneyimi sunmak için referans olarak Android Kotlin ImageInImage örneğine bakın.
Hareketle gezinmeden PiP moduna daha sorunsuz geçişler yapın
Android 12'den itibaren setAutoEnterEnabled
işareti, hareketle gezinme kullanarak (örneğin, tam ekrandan ana ekrana yukarı kaydırırken) PiP modunda video içeriğine geçiş için çok daha akıcı bir animasyon sağlar.
Bu değişikliği yapmak için aşağıdaki adımları tamamlayın ve bir referans için 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
ile birlikte en güncelPictureInPictureParams
uygulamasını erkenden arayın. Uygulama, Android 11'de olduğu gibionUserLeaveHint
geri çağırmasını beklemez.Örneğin, en boy oranı değişirse ilk oynatmada ve sonraki oynatmada
setPictureInPictureParams
çağırmak isteyebilirsiniz.Gerekli olduğunda
setAutoEnterEnabled(false)
numaralı telefonu arayın. Örneğin, mevcut oynatma duraklatılmış durumdaysa muhtemelen PiP'yi girmek istemezsiniz.
PiP moduna girmek ve bu moddan çıkmak için uygun bir sourceRectHint
ayarlayın
PiP'nin Android 8.0'da kullanıma sunulmasından itibaren setSourceRectHint
, pencere içinde pencere moduna geçişten sonra görülebilen etkinlik alanını (örneğin, bir video oynatıcıda video görüntüleme sınırları) belirtmiştir.
Android 12 ile sistem, PiP moduna girerken ve bu moddan çıkarken çok daha akıcı bir animasyon uygulamak için sourceRectHint
özelliğini kullanır.
PiP moduna girerken ve bu moddan çıkarken sourceRectHint
uygulamasını doğru şekilde ayarlamak için:
PictureInPictureParams
yapısınısourceRectHint
şeklinde uygun sınırları kullanarak oluşturun. Video oynatıcıya bir düzen değişikliği işleyicisi eklemenizi de ö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şini başlatmadan önce
sourceRectHint
'i güncelleyin. Sistem, PiP modundan çıkmak üzereyken etkinliğin görünüm hiyerarşisi, hedef yapılandırmasına göre yerleştirilir (örneğin, tam ekran). 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şleyicisi 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çerik için sorunsuz yeniden boyutlandırmayı devre dışı bırak
Android 12'de, PiP penceresinde video olmayan içerikler yeniden boyutlandırıldığında çok daha akıcı bir çapraz geçiş animasyonu sağlayan setSeamlessResizeEnabled
işareti eklenir. Önceden, video dışı içerikleri PiP penceresinde yeniden boyutlandırmak dikkat çekici görsel yapılar oluşturabiliyordu.
Video olmayan içerikler için kesintisiz yeniden boyutlandırmayı devre dışı bırakmak üzere:
Kotlin
setPictureInPictureParams(PictureInPictureParams.Builder() .setSeamlessResizeEnabled(false) .build())
Java
setPictureInPictureParams(new PictureInPictureParams.Builder() .setSeamlessResizeEnabled(false) .build());
PiP sırasında kullanıcı arayüzünü işleme
Etkinlik, PiP moduna girdiğinde veya bu moddan çıktığında sistem, Activity.onPictureInPictureModeChanged()
veya Fragment.onPictureInPictureModeChanged()
modunu çağırır.
Etkinliğin kullanıcı arayüzü öğelerini yeniden çizmek için bu geri çağırmaları geçersiz kılmanız gerekir. PiP modunda etkinliğiniz küçük bir pencerede gösterilir. Kullanıcılar, PiP modundayken uygulamanızın kullanıcı arayüzü öğeleriyle etkileşimde bulunamaz ve küçük kullanıcı arayüzü öğelerinin ayrıntılarını görmek zor olabilir. 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 hale geldiğinde geri yükleyin:
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. ... } }
Kontrol ekle
PiP penceresi, kullanıcı pencerenin menüsünü açtığında (mobil cihazda pencereye dokunarak veya TV uzaktan kumandasından menüyü seçerek) kontrolleri gösterebilir.
Bir uygulamada etkin medya oturumu varsa oynat, duraklat, sonraki ve önceki kontroller görünür.
Ayrıca, PiP moduna girmeden önce PictureInPictureParams.Builder.setActions()
ile PictureInPictureParams
derleyerek ve PiP moduna girerken parametreleri enterPictureInPictureMode(android.app.PictureInPictureParams)
veya setPictureInPictureParams(android.app.PictureInPictureParams)
kullanarak ileterek özel işlemleri açıkça belirtebilirsiniz.
Dikkatli olun. getMaxNumPictureInPictureActions()
değerinden daha fazla değer eklemeye çalışırsanız yalnızca maksimum sayıda sayıyı alırsınız.
PiP modundayken video oynatmaya devam ediliyor
Etkinliğiniz PIP'ye geçtiğinde sistem, etkinliği duraklatılmış duruma getirir ve etkinliğin onPause()
yöntemini çağırır. Video oynatma duraklatılmamalı ve PiP modundayken duraklatıldığında oynatılmaya devam etmelidir.
Android 7.0 ve sonraki sürümlerde, sistem etkinliğinizin onStop()
ve onStart()
değerlerini çağırdığında, video oynatmayı duraklatıp devam ettirmeniz gerekir. Bu sayede uygulamanızın onPause() işlevinde PiP modunda olup olmadığını kontrol etmek ve oynatmaya açık bir şekilde devam etmek zorunda kalmazsınız.
setAutoEnterEnabled
işaretini true
olarak ayarlamadıysanız ve onPause()
uygulamanızda oynatmayı duraklatmanız gerekiyorsa isInPictureInPictureMode()
yöntemini çağırarak PiP modunu kontrol edin ve oynatma işlemini uygun şekilde gerçekleştirin. Ö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 tekrar tam ekran moduna geçtiğinde sistem, etkinliğinizi devam ettirir ve onResume()
yönteminizi çağırır.
PiP için tek bir oynatma etkinliği kullanma
Uygulamanızda, kullanıcı ana ekranda içeriğe göz atarken yeni bir video seçebilir ve video oynatma etkinliği PiP modunda olabilir. Yeni videoyu, kullanıcının kafasını karıştırabilecek yeni bir etkinlik başlatmak yerine mevcut oynatma etkinliğinde tam ekran modunda oynatın.
Video oynatma isteklerinde tek bir etkinliğin kullanıldığından ve gerektiğinde PiP moduna geçtiğinden veya bu moddan çıktığından emin olmak için manifest dosyanızda etkinliğin android:launchMode
değerini singleTask
olarak ayarlayın:
<activity android:name="VideoActivity"
...
android:supportsPictureInPicture="true"
android:launchMode="singleTask"
...
Etkinliğinizde, onNewIntent()
öğesini geçersiz kılın ve yeni videoyu işleyerek gerekirse mevcut videonun oynatılmasını durdurun.
En iyi uygulamalar
RAM'i düşük olan cihazlarda PiP devre dışı bırakılabilir. Uygulamanız PiP'yi kullanmadan önce hasSystemFeature(PackageManager.FEATURE_PICTURE_IN_PICTURE)
numaralı telefonu arayarak bu özelliğin kullanılabilir olup olmadığını kontrol edin.
PIP, tam ekran video oynatan etkinliklere yöneliktir. Etkinliğinizi PiP moduna geçirirken video içeriği dışında hiçbir şey göstermekten kaçının. Etkinliğinizin PiP moduna girdiğini izleyin ve PIP sırasında kullanıcı arayüzünü kullanma bölümünde açıklandığı gibi kullanıcı arayüzü öğelerini gizleyin.
PiP modundayken bir etkinlik varsayılan olarak giriş odağı almaz. PiP modundayken giriş etkinliklerini almak için MediaSession.setCallback()
değerini kullanın.
setCallback()
uygulamasını kullanmayla ilgili daha fazla bilgi için Ne Çalıyor? kartı görüntüleme konusuna bakın.
Uygulamanız PiP modundayken PiP penceresinde video oynatma, müzik çalar uygulaması veya sesli arama uygulaması gibi başka uygulamalarda 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 ele alın. PiP modundayken ses odağının kaybolmasıyla ilgili bildirim alırsanız videoyu oynatmayı duraklatın veya durdurun.
Uygulamanız PIP'ye girmek üzereyken yalnızca en üstteki etkinliğin pencere içinde pencere moduna girdiğini unutmayın. Birden fazla pencereli cihazlarda olduğu gibi bazı durumlarda aşağıdaki etkinliğin tekrar gösterilmesi ve PiP etkinliğinin yanında tekrar görünür hale gelmesi mümkündür. Bu durumu uygun şekilde ele almanız gerekir. onResume()
veya onPause()
geri araması almak için aşağıdaki işlemleri de yapmanız gerekir. Kullanıcının etkinlikle etkileşimde bulunması da mümkündür. Örneğin, PiP modunda bir video listesi etkinliğiniz ve video oynatma etkinliğiniz gösteriliyorsa kullanıcı listeden yeni bir video seçebilir ve PiP etkinliği buna göre güncellenir.
Ek örnek kod
Android'de yazılmış örnek bir uygulamayı indirmek için Pencere İçinde Pencere Örneği'ne bakın. Kotlin ile yazılmış örnek bir uygulamayı indirmek için Android Resim İçinde Resim Örneği (Kotlin) bölümüne bakın.