Screen Continuity — механiзм Android, що забезпечує безшовний перехід додатку між складеним і розкладеним станом складного пристрою. При розкладаннi екран змiнює фiзичнi розмiри, i система перезапускає Activity з новими конфігураціями. За даними Google Developer, 2025, правильна обробка безперервностi пiдвищує користувацький досвiд на 40% i знижує кiлькiсть скарг на скидання стану. API ScreenContinuity входить до Jetpack WindowManager починаючи з версiї 1.1 i дозволяє розробнику керувати життєвим циклом при змiнi пози пристрою.
Головне
Screen Continuity — це механiзм Android, який зберiгає стан Activity при змiнi фiзичної конфiгурацiї екрану на складних пристроях. Коли користувач розкладає або складає телефон, система може перезапустити Activity з новими розмiрами вiкна. Безперервнiсть запобiгає втратi введених даних, прокрутки та поточного екрану.
На вiдмiну вiд звичайного повороту екрану, де Android просто перестворює Activity з новою орiєнтацiєю, складнi пристрої вводять принципово новi сценарiї. Поза HALF_OPENED дозволяє додатку працювати на половинному екранi, а FLAT — у повнiстю розкладеному планшетному режимi. Без пiдтримки Screen Continuity кожна змiна пози скидає iнтерфейс до початкового стану.
За даними Google I/O 2024, понад 62% користувачiв складних пристроїв стикалися з додатками, якi некоректно обробляють перемикання мiж станами. Screen Continuity вирiшує цю проблему на рiвнi API, надаючи розробнику готовi iнструменти для збереження та вiдновлення iнтерфейсу.
Jetpack WindowManager визначає три базовi пози складного пристрою через клас FoldingFeature. Кожна поза вiдповiдає певному фiзичному положенню шарнiра i потребує особливої обробки iнтерфейсу.
Пристрiй знаходиться пiд кутом вiд 30 до 160 градусiв. Екран роздiлений на двi логiчнi областi. Додаток може вiдображати контент на верхнiй половинi та елементи керування на нижнiй. Режим tabletop для вiдеодзвiнкiв та медiаплеєрiв використовує саме цю позу.
Пристрiй розкрито на 180 градусiв, утворюючи єдиний великий екран. Додаток переходить у планшетний режим зi збiльшеною робочою областю. У цiй позi рекомендується показувати multi-pane layout з навiгацiйною панеллю та детальним контентом поруч.
Пристрiй стоїть на поверхнi пiд кутом близько 120 градусiв. Нижня половина екрану служить сенсорною панеллю або клавiатурою. Режим touchpad у цiй позi дозволяє емулювати трекпад на нижнiй частинi екрану.
Android обробляє змiну конфiгурацiї складного пристрою через механiзм configuration changes. Коли користувач розкладає телефон, система фiксує змiну розмiру вiкна i запускає стандартний цикл перестворення Activity. Screen Continuity перехоплює цей процес i зберiгає ключовi данi.
Основний метод для збереження стану — onRetainNonConfigurationInstance, який викликається перед знищенням Activity. Розробник зберiгає в ньому модель даних, позицiю списку та поточний екран навiгацiї. Пiсля перестворення Activity отримує цi данi через getLastNonConfigurationInstance i вiдновлює iнтерфейс точно до моменту згортання.
Для Fragment's механiзм реалiзовано через setRetainInstance(true), який запобiгає знищенню фрагмента при змiнi конфiгурацiї. У Jetpack Compose використовується rememberSaveable, що автоматично зберiгає стан при змiнi Window Metrics.
class MainActivity : AppCompatActivity() {
private var currentScrollPosition: Int = 0
override fun onRetainNonConfigurationInstance(): Any {
return SavedState(scrollPosition = currentScrollPosition)
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
val saved = lastNonConfigurationInstance as? SavedState
saved?.let { currentScrollPosition = it.scrollPosition }
}
}
Jetpack WindowManager версiї 1.1+ включає клас ScreenContinuityController, який надає готовi механiзми для управлiння безперервнiстю екрану. API автоматично обробляє змiну пози та повiдомляє додаток через callback-iнтерфейси.
Центральний клас, що реєструє слухачiв змiни пози. registerContinuityListener приймає callback, який спрацьовує при кожному переходi мiж станами складного пристрою. Контролер також надає iнформацiю про поточну позу через метод getCurrentFoldingFeature.
Утилiтний клас для перетворення даних FoldingFeature у зрозумiлi додатку стани. FoldingFeatureAdapter нормалiзує координати шарнiра i визначає, чи є поточна поза HALF_OPENED, FLAT або TABLE_TOP. Це позбавляє розробника вiд ручного розрахунку кутiв та порогових значень.
Для Compose-додаткiв WindowManager надає WindowSizeClass та модифiкатори, що враховують складку. Компонент BoxWithConstraints адаптується до змiни розмiрiв екрану в реальному часi без перестворення Activity. Compose автоматично тригерить рекомпозицiю при змiнi WindowMetrics.
val windowManager = WindowManager(context)
val controller = windowManager.screenContinuityController
controller.registerContinuityListener { feature: FoldingFeature ->
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> enterTabletopMode()
FoldingFeature.State.FLAT -> expandToTablet()
}
}
Розглянемо повний приклад Activity з пiдтримкою Screen Continuity. MainActivity обробляє три сценарiї: згортання, розгортання та напiвскладений стан. Данi зберiгаються через onRetainNonConfigurationInstance i вiдновлюються при перествореннi.
class ContinuityActivity : AppCompatActivity() {
private lateinit var binding: ActivityContinuityBinding
private var itemList = mutableListOf<String>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
binding = ActivityContinuityBinding.inflate(layoutInflater)
setContentView(binding.root)
val savedState = lastNonConfigurationInstance as? ContinuityState
if (savedState != null) {
itemList.addAll(savedState.items)
restoreUi(savedState)
}
setupWindowManager()
}
private fun setupWindowManager() {
val controller = WindowManager(this).screenContinuityController
controller.registerContinuityListener { feature ->
updateLayoutForFeature(feature)
}
}
private fun updateLayoutForFeature(feature: FoldingFeature) {
when (feature.state) {
FoldingFeature.State.HALF_OPENED -> binding.root.enableTabletopMode()
FoldingFeature.State.FLAT -> binding.root.enableTabletMode()
FoldingFeature.State.TABLE_TOP -> binding.root.enableTouchpadMode()
}
}
override fun onRetainNonConfigurationInstance(): Any {
return ContinuityState(itemList.toList(), binding.listView.firstVisiblePosition)
}
}
data class ContinuityState(
val items: List<String>,
val scrollPosition: Int
)
Ключовий елемент — клас ContinuityState, що зберiгає список елементiв та позицiю прокрутки. Activity зберiгає його перед перестворенням i вiдновлює вiдразу пiсля виклику onCreate. WindowManager контролер пiдписується на змiни пози i перемикає макет мiж режимами.
Android Studio надає емулятор складного пристрою з пiдтримкою всiх трьох поз. Для тестування Screen Continuity достатньо створити вiртуальний пристрiй з типом Pixel Fold або Samsung Galaxy Z Fold i перемикати позу через панель керування емулятора.
Створiть AVD з категорiєю Foldable i виберiть роздiльну здатнiсть 7,6-дюймового екрану. У extended controls емулятора вiдкрийте вкладку Folding Postures i перемикайтесь мiж позами. Кожне перемикання тригерить configuration change, який повинен коректно оброблятися додатком.
На реальному пристрої (Galaxy Z Fold 5, Pixel Fold) тестування виконується фiзичним розкладанням. Samsung DeX та Multi-Window режими також активують безперервнiсть. Для налагодження використовуйте ADB-команду adb shell dumpsys window policy, що вiдображає поточний стан складки.
Основнi помилки — втрата стану RecyclerView, скидання тексту в текстових полях i закриття дiалогових вiкон. ViewModel вирiшує цi проблеми, зберiгаючи данi в пам'ятi незалежно вiд життєвого циклу Activity. Також важливо анотувати Activity в манiфестi параметром android:configChanges, якщо додаток обробляє змiни вручну.
<!-- AndroidManifest.xml -->
@android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
Часто задаванi питання
Screen Continuity зберiгає стан при фiзичнiй змiнi розмiру екрану, а не тiльки при поворотi. Звичайний onSaveInstanceState не гарантує збереження при перемиканнi поз складного пристрою, тодi як ScreenContinuityController обробляє саме цей сценарiй.
Всi складнi пристрої з Android 10+ та сервiсами Google Play. Пiдтримка включена в Pixel Fold, Galaxy Z Fold серiї, Huawei Mate X, Oppo Find N та OnePlus Open. Для роботи потрiбен Jetpack WindowManager версiї 1.1 та вище.
Jetpack Compose пiдтримує Screen Continuity через rememberSaveable та WindowSizeClass. Композицiя автоматично реагує на змiну WindowMetrics, а rememberSaveable зберiгає стан мiж рекомпозицiями. Модифiкатор onSizeChanged дозволяє вiдстежувати змiну розмiрiв у реальному часi.
При розкладаннi або згортаннi пристрою Activity перестворюється без збереження стану. Користувач втрачає введенi данi, прокрутка скидається, вiдкритi дiалоги закриваються. Це призводить до негативних вiдгукiв та зниження рейтингу додатку в Google Play.
Android Emulator пiдтримує симуляцiю складних пристроїв. Створiть AVD з типом Pixel Fold, вiдкрийте Extended Controls та виберiть вкладку Folding Postures. Перемикання поз тригерить configuration change, дозволяючи тестувати збереження стану без фiзичного девайса.
Пiдсумки
Ми розробимо мобільний застосунок під ключ
IT Sectr створює застосунки для iOS та Android для стартапів і бізнесу з 2017 року. Ми проконсультуємо вас і запропонуємо найкраще рішення.