ضبط إعدادات تطبيقك في وضع "نافذة ضمن النافذة" (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")
    }

إضافة ميزة "نافذة ضمن النافذة" إلى تطبيق الإجازات على الإصدارات السابقة من 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.