کتابخانه Jetpack «تصویردرتصویر» (PiP) راهحلی ساده و قدرتمند برای توسعهدهندگان برنامه Android ارائه میدهد تا عملکرد PiP را بهویژه برای برنامههای بازپخش رسانه، ارتباط تصویری، و پیمایش پیادهسازی کنند. این کتابخانه با ارائه یک API یکپارچه، به حذف کد تکراری، اشکالات رایج درونبرنامهای، و بهبود کیفیت کلی تجربه کاربری «تصویردرتصویر» کمک میکند.
کتابخانه PiP Jetpack با پرداختن به چندین چالش و ناسازگاری کلیدی در سراسر بومسازگان Android، میاناهای برنامهسازی کاربردی PiP موجود را تسهیل میکند:
- تکهتکه شدن سیستمعامل: کتابخانه بهطور خودکار تفاوتهای موجود در فراخوانیهای PiP API در نسخههای مختلف Android را مدیریت میکند، برای مثال، از
enterPictureInPictureModeقبلاز Android 12 و ازisAutoEnterEnabledبعداز آن استفاده میکند، بنابراین توسعهدهندگان نیازی به مدیریت تفاوتهای نسخه ندارند. - پارامترهای نادرست PiP: این ویژگی راهحلی یکپارچه برای تنظیم صحیح پارامترهای PiP، برای مثال
setSourceRectHint، ارائه میدهد تا بتوانید درطول پخش رسانه، پویانماییهای روان و با کیفیت بالا ایجاد کنید. - بازخوانهای وضعیت PiP یکپارچه: این ویژگی
onPictureInPictureModeChangedوonPictureInPictureUiStateChangedرا در یک واسط بازخوان یکپارچه واحد (PictureInPictureDelegate.OnPictureInPictureEventListener) برای مدیریت سادهشده وضعیت و واسط کاربر ادغام میکند. - کاهش کد کلیشهای: این کتابخانه با ارائه مجموعههای ازپیش تعریفشده
RemoteActionsبرای موارد استفاده رایج، مانند کنترلهای بازپخش و کنشهای تماس تصویری، مقدار کد کلیشهای تکراری را کاهش میدهد. - آمادهسازی برای آینده: ویژگیهای بیشتر «تصویردرتصویر» ازطریق کتابخانه Jetpack ارائه میشود و به پذیرندگان امکان میدهد با حداقل تلاش یا بدون تلاش به عملکرد اضافی دسترسی پیدا کنند.
گردش کار انتقال
دسته مورد استفاده برنامه و منطق PiP قدیمی را شناسایی کنید:
دستهها: بازپخش ویدیو، پیمایش، یا تماس تصویری.
منطق PiP قدیمی برای شناسایی:
onUserLeaveHintsetAutoEnterEnabledonPictureInPictureModeChangedonPictureInPictureUiStateChangedsetPictureInPictureParams.
۲. پیکربندی AndroidManifest
مطمئن شوید «فعالیتی» که وارد «تصویردرتصویر» میشود در AndroidManifest.xml با
configChanges لازم از پشتیبانی اعلام میکند تا از راهاندازی مجدد غیرضروری جلوگیری شود:
<activity
android:name="VideoActivity" android:supportsPictureInPicture="true"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation">
</activity>
۳. راهاندازی محیط
وابستگیهای لازم را به build.gradle اضافه کنید:
dependencies {
implementation("androidx.core:core:1.18.0")
implementation("androidx.activity:activity:1.13.0")
implementation("androidx.core:core-pip:1.0.0-alpha02") }
برای وابستگیها از جدیدترین کتابخانههای AndroidX استفاده کنید و برای دریافت اطلاعات به صفحه انتشارها مراجعه کنید.
۴. انتخاب و مقداردهی اولیه الگو
الگوی پیادهسازی را که بهترین تناسب را با مورد استفاده برنامه دارد انتخاب کنید:
- پیمایش و تماس تصویری:
BasicPictureInPicture؛ تغییر اندازه یکپارچه معمولاً پشتیبانی نمیشود و به اشاره مستطیل منبع نیاز ندارید. - پخش ویدیو:
VideoPlaybackPictureInPicture؛ بهطور خودکار حدود نمای پخشکننده را برای اشاره مستطیل منبع ردیابی میکند و بهطور پیشفرض تغییر اندازه یکپارچه را فعال میکند.
برای استفاده از «کتابخانه Jetpack»، پیادهسازی سفارشی PiP موجود را با «میاناهای برنامهسازی کاربردی کتابخانه Jetpack» جایگزین کنید. پیچیدگی و هزینه پذیرش براساس پیادهسازی فعلی برنامه متفاوت خواهد بود.
بخشهای زیر برخیاز موارد استفاده معمول از PiP و مراحل پیادهسازی لازم را توضیح میدهد:
پیمایش
برنامه کتابخانه را از وضعیت فعال یا غیرفعال بودن پیمایش مطلع میکند و نسبت ابعادی را تنظیم میکند. کتابخانه Jetpack بقیه کارها را انجام میدهد.
تفاوتهای کلیدی:
- نیازی نیست که در سمت برنامه بین ورود خودکار و ورود قدیمی تفاوت قائل شوید.
- میاناهای بازخوانی یکپارچه.
- سازنده جدید
PictureInPictureParamsبرای سازگاری با نسخه قدیمی.
تماس تصویری
برنامه کتابخانه را از وضعیت فعال یا غیرفعال تماس مطلع میکند و نسبت ابعادی را تنظیم میکند.
تفاوتهای کلیدی:
- نیازی نیست که در سمت برنامه بین ورود خودکار و ورود قدیمی تفاوت قائل شوید.
- میاناهای بازخوانی یکپارچه.
- سازنده جدید
PictureInPictureParamsبرای سازگاری با نسخه قدیمی. - نمادهای کنش استانداردشده برای تماس تصویری.
۵. انتقال کد
- منطق ورودی: منطق مختص میانای برنامهسازی کاربردی مثل
setAutoEnterEnabledبرای Android 12 و بالاتر، یاonUserLeaveHintبرای Android 11 و پایینتر را باsetEnabledجایگزین کنید. هرزمان وضعیت واجدشرایط بودن PiP تغییر کرد، این عملگر را راهاندازی کنید. - پاسخهای تماس:
onPictureInPictureModeChanged(تغییر چیدمان) وonPictureInPictureUiStateChanged(پویانمایی/وضعیتها) را در پاسخ تماس رویدادمحور یکپارچهonPictureInPictureEventادغام کنید. - کنشها و پارامترها: هرگاه پارامترها تغییر کرد، آنها را بااستفاده از
setActionsوsetAspectRatioدر نمونه الگو بهروز کنید.
الگوهای پیادهسازی مرجع
نمونههایی از پیادهسازیها.
ناوبری و تماس تصویری
class NavOrVideoCallJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener { private lateinit var pictureInPictureImpl: BasicPictureInPicture override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) pictureInPictureImpl = BasicPictureInPicture(this) // BasicPictureInPicture is ideal for Navigation and Video call use cases. pictureInPictureImpl.addOnPictureInPictureEventListener( ContextCompat.getMainExecutor(this), this ) setContent { } } override fun onPictureInPictureEvent( event: PictureInPictureDelegate.Event, config: Configuration? ) { when (event) { PictureInPictureDelegate.Event.ENTERED -> { /* Toggle to PiP layout */ } PictureInPictureDelegate.Event.EXITED -> { /* Toggle to Full-screen layout */ } PictureInPictureDelegate.Event.STASHED -> { /* Optional: PiP is stashed */ } PictureInPictureDelegate.Event.UNSTASHED -> { /* Optional: PiP is unstashed */ } } } }
بازپخش ویدیو
class VideoPlaybackJpipActivity : ComponentActivity(), PictureInPictureDelegate.OnPictureInPictureEventListener { private lateinit var pictureInPictureImpl: VideoPlaybackPictureInPicture override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) pictureInPictureImpl = VideoPlaybackPictureInPicture(this) pictureInPictureImpl.addOnPictureInPictureEventListener( ContextCompat.getMainExecutor(this), this ) setContent { ContentScreen(pictureInPictureImpl) } } override fun onPictureInPictureEvent( event: PictureInPictureDelegate.Event, config: Configuration? ) { when (event) { PictureInPictureDelegate.Event.ENTER_ANIMATION_START -> { /* Hide overlays */ } PictureInPictureDelegate.Event.ENTER_ANIMATION_END -> { /* Animation finished */ } PictureInPictureDelegate.Event.ENTERED -> { /* Switch to PiP layout */ } PictureInPictureDelegate.Event.STASHED -> { /* PiP stashed */ } PictureInPictureDelegate.Event.UNSTASHED -> { /* PiP unstashed */ } PictureInPictureDelegate.Event.EXITED -> { /* Return to full-screen */ } } } @Composable fun ContentScreen(pipController: VideoPlaybackPictureInPicture) { DisposableEffect(pipController) { onDispose { pipController.close() } } } }