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

في رمز الإنشاء، نفِّذ ما يلي:

  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: () -> Unit = {
            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 للدخول إلى وضع PiP عند التمرير سريعًا. يقدّم هذا الإجراء رسومًا متحركة أكثر سلاسة من الانتقال إلى 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 لضبط نسبة عرض إلى ارتفاع نافذة "وضع الصورة في الصورة"

لضبط نسبة العرض إلى الارتفاع لشاشة "صورة في صورة"، يمكنك اختيار نسبتَي عرض إلى ارتفاع معيّنتَين أو استخدام عرض الفيديو وارتفاعه في المشغّل. إذا كنت تستخدم مشغّل media3، تأكَّد من أنّ المشغّل ليس فارغًا ومن أنّ حجم الفيديو في المشغّل ليس مساويًا لـ [VideoSize.UNKNOWN][6] قبل ضبط ونسة العرض إلى الارتفاع.

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)

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