ضبط إعدادات تطبيقك في وضع "نافذة ضمن النافذة" (PIP)

في علامة النشاط لملف AndroidManifest.xml، اتّبِع الخطوات التالية:

  1. أضِف supportsPictureInPicture واضبطه على true للإشارة إلى أنّك ستستخدم ميزة "نافذة ضمن النافذة" في تطبيقك.
  2. أضِف configChanges واضبطه على orientation|screenLayout|screenSize|smallestScreenSize لتحديد أنّ نشاطك يتعامل مع تغييرات ضبط التنسيق. بهذه الطريقة، لا تتم إعادة تشغيل نشاطك عند حدوث تغييرات في التنسيق أثناء الانتقال إلى وضع "نافذة ضمن النافذة".
<activity
    android:name=".SnippetsActivity"
    android:exported="true"
    android:supportsPictureInPicture="true"
    android:configChanges="orientation|screenLayout|screenSize|smallestScreenSize"
    android:theme="@style/Theme.Snippets">

في رمز Compose، اتّبِع الخطوات التالية:

  1. يمكنك إضافة هذه الإضافة على Context. ستستخدم هذه الإضافة عدة مرات خلال الدليل للوصول إلى النشاط.
    internal fun Context.findActivity(): ComponentActivity {
        var context = this
        while (context is ContextWrapper) {
            if (context is ComponentActivity) return context
            context = context.baseContext
        }
        throw IllegalStateException("Picture in picture should be called in the context of an Activity")
    }

إضافة ميزة PiP عند مغادرة التطبيق لإصدارات Android الأقدم من Android 12

لإضافة ميزة "نافذة ضمن النافذة" في الإصدارات الأقدم من Android 12، استخدِم addOnUserLeaveHintProvider. اتّبِع الخطوات التالية لإضافة ميزة "نافذة ضمن النافذة" في الإصدارات السابقة من Android 12:

  1. أضِف حاجزًا للإصدارات بحيث لا يمكن الوصول إلى هذا الرمز إلا في الإصدارات من O إلى R.
  2. استخدِم DisposableEffect مع Context كمفتاح.
  3. داخل DisposableEffect، حدِّد سلوك onUserLeaveHintProvider عند تفعيله باستخدام دالة lambda. في دالة lambda، استدعِ enterPictureInPictureMode() في findActivity() ومرِّر PictureInPictureParams.Builder().build().
  4. أضِف addOnUserLeaveHintListener باستخدام findActivity() وأدخِل دالة lambda.
  5. في onDispose، أضِف removeOnUserLeaveHintListener باستخدام findActivity() ومرِّر دالة lambda.

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
    Build.VERSION.SDK_INT < Build.VERSION_CODES.S
) {
    val context = LocalContext.current
    DisposableEffect(context) {
        val onUserLeaveBehavior = Runnable {
            context.findActivity()
                .enterPictureInPictureMode(PictureInPictureParams.Builder().build())
        }
        context.findActivity().addOnUserLeaveHintListener(
            onUserLeaveBehavior
        )
        onDispose {
            context.findActivity().removeOnUserLeaveHintListener(
                onUserLeaveBehavior
            )
        }
    }
} else {
    Log.i("PiP info", "API does not support PiP")
}

إضافة ميزة "نافذة ضمن النافذة" عند مغادرة التطبيق لإصدارات Android 12 والإصدارات الأحدث

في الإصدارات الأحدث من Android 12، تتم إضافة PictureInPictureParams.Builder من خلال مُعدِّل يتم تمريره إلى مشغّل الفيديو في التطبيق.

  1. أنشئ modifier واستدعِ onGloballyPositioned فيه. سيتم استخدام إحداثيات التخطيط في خطوة لاحقة.
  2. أنشِئ متغيّرًا لـ PictureInPictureParams.Builder().
  3. أضِف عبارة if للتحقّق مما إذا كانت حزمة SDK هي S أو إصدار أحدث. في هذه الحالة، أضِف setAutoEnterEnabled إلى أداة الإنشاء واضبطها على true للدخول إلى وضع "نافذة ضمن النافذة" عند التمرير السريع. يوفّر ذلك حركة أكثر سلاسة من الانتقال إلى enterPictureInPictureMode.
  4. استخدِم findActivity() للاتصال بـ "setPictureInPictureParams()". اتصِل بـ "build()" على الرقم builder ومرِّر المكالمة.

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(true)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}
VideoPlayer(pipModifier)

استخدِم setAspectRatio لضبط نسبة العرض إلى الارتفاع في نافذة "نافذة ضمن النافذة"

لضبط نسبة العرض إلى الارتفاع لنافذة &quot;نافذة ضمن النافذة&quot;، يمكنك اختيار نسبة عرض إلى ارتفاع معيّنة أو استخدام عرض وارتفاع حجم الفيديو في المشغّل. إذا كنت تستخدم مشغّل media3، تأكَّد من أنّ المشغّل ليس فارغًا وأنّ حجم الفيديو في المشغّل لا يساوي VideoSize.UNKNOWN قبل ضبط نسبة العرض إلى الارتفاع.

val context = LocalContext.current

val pipModifier = modifier.onGloballyPositioned { layoutCoordinates ->
    val builder = PictureInPictureParams.Builder()
    if (shouldEnterPipMode && player != null && player.videoSize != VideoSize.UNKNOWN) {
        val sourceRect = layoutCoordinates.boundsInWindow().toAndroidRectF().toRect()
        builder.setSourceRectHint(sourceRect)
        builder.setAspectRatio(
            Rational(player.videoSize.width, player.videoSize.height)
        )
    }

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
        builder.setAutoEnterEnabled(shouldEnterPipMode)
    }
    context.findActivity().setPictureInPictureParams(builder.build())
}

VideoPlayer(pipModifier)

إذا كنت تستخدم مشغّل فيديو مخصّصًا، اضبط نسبة العرض إلى الارتفاع على ارتفاع المشغّل وعرضه باستخدام البنية المحدّدة لمشغّل الفيديو. يُرجى العِلم أنّه في حال تغيير حجم المشغّل أثناء الإعداد، سيتعطّل تطبيقك إذا تجاوز الحدود الصالحة لنسبة العرض إلى الارتفاع. قد تحتاج إلى إضافة عمليات تحقّق حول وقت احتساب نسبة العرض إلى الارتفاع، على غرار ما يتم في مشغّل media3.