Впровадження Multi-Window для Android-додатків
Multi-Window — це режим розділеного екрана на Android 7.0+ (API 24) та режим «картинка в картинці» (Picture-in-Picture) для Android 8.0+ (API 26). Починаючи з Android 12, режим розділеного екрана за замовчуванням ввімкнено для всіх додатків, якщо явно не вимкнено через android:resizeableActivity="false". Це означає, що ваш додаток уже може бути на розділеному екрані у користувачів, і якщо він до цього не готовий — користувацький інтерфейс ламається.
Що означає «готовий до Multi-Window»
Додаток, що працює на розділеному екрані, отримує змінені розміри вікна кілька разів на секунду при рухові розділювача. Кожна така зміна викликає або onConfigurationChanged(), або пересоздання Activity (якщо android:configChanges не вказано). Якщо Activity пересоздається при кожному русі розділювача, користувачі бачать мигання та втрату стану.
Правильний підхід — оголосити в маніфесті, що Activity сама обробляє зміни конфігурації:
<activity
android:name=".MainActivity"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
android:resizeableActivity="true" />
У onConfigurationChanged() перераховуйте layout без пересоздання—використовуйте WindowMetrics API (API 30+) або DisplayMetrics для старіших версій.
Адаптивний UI. З Jetpack Compose: використовуйте BoxWithConstraints або WindowSizeClass з androidx.window:window для визначення поточного класу вікна (Compact, Medium, Expanded). Не кодуйте жорстко «планшетний layout» на основі isTablet()—перевіряйте фактичний розмір доступного вікна, який у режимі розділеного екрана на планшеті може бути таким же, як на телефоні.
Picture-in-Picture
PiP активується через enterPictureInPictureMode(PictureInPictureParams). Типовий варіант використання — відеоплеєр. При переході до PiP:
val params = PictureInPictureParams.Builder()
.setAspectRatio(Rational(16, 9))
.setActions(listOf(
RemoteAction(/* пауза/відтворення */),
RemoteAction(/* наступна композиція */)
))
.build()
enterPictureInPictureMode(params)
RemoteAction представляє кнопки, видимі у вікні PiP. Натискання надсилає PendingIntent—зазвичай BroadcastReceiver у Activity.
Проблема: onStop() викликається при переході до PiP. Якщо відеоплеєр зупиняється в onStop(), відтворення перериває. Рішення: перевіряйте isInPictureInPictureMode у onStop() і не зупиняйте плеєр.
override fun onStop() {
super.onStop()
if (!isInPictureInPictureMode) {
player.pause()
}
}
onPictureInPictureModeChanged() — колбек для оновлення UI: приховуйте кнопки керування у режимі PiP, показуючи лише вміст відео.
Перетягування елементів між вікнами
Починаючи з API 24, підтримується перетягування між додатками на розділеному екрані. Для отримання: використовуйте View.setOnDragListener() і обробляйте DragEvent.ACTION_DROP. Для ініціалізації: використовуйте View.startDragAndDrop() з ClipData. Починаючи з API 33, поліпшений DropHelper з androidx.draganddrop спрощує обробку різних типів MIME.
Режим Freeform
На ChromeOS та деяких пристроях Android додатки працюють у режимі freeform—довільний розмір вікна. android:resizeableActivity="true" плюс правильна обробка onConfigurationChanged — це необхідні умови. Тестування: Developer Options → Force desktop mode (на підтримуваних пристроях) або емулятор ChromeOS.
Бібліотека WindowManager (androidx.window:window:1.3.x) надає WindowInfoTracker з Flow<WindowLayoutInfo>—для складних пристроїв (Fold, Flip) це дозволяє вам реагувати на стан шарніра (напівзакрите, режим планшета). Для додатків, які повинні підтримувати пристрої Galaxy Z Fold, правильна адаптація неможлива без цієї бібліотеки.
Впровадження повної підтримки Multi-Window з PiP, адаптивним UI та тестуванням займає 3–5 днів. Вартість розраховується індивідуально після оцінки поточного стану коду користувацького інтерфейсу.







