Screen Continuity — механизъм на Android, осигуряващ безпроблемен преход на приложението между сгънато и разгънато състояние на сгъваемо устройство. При разгъване екранът променя физическите си размери и системата рестартира Activity с нови конфигурации. Според Google Developer, 2025, правилната обработка на непрекъснатостта подобрява потребителското изживяване с 40% и намалява броя на оплакванията за нулиране на състоянието. API ScreenContinuity е част от Jetpack WindowManager от версия 1.1 и позволява на разработчика да управлява жизнения цикъл при промяна на позата на устройството.
Основни точки
Screen Continuity е механизъм на Android, който запазва състоянието на Activity при промяна на физическата конфигурация на екрана на сгъваеми устройства. Когато потребителят разгъне или сгъне телефона, системата може да рестартира Activity с нови размери на прозореца. Непрекъснатостта предотвратява загубата на въведени данни, позицията на превъртане и текущия екран.
За разлика от обикновеното завъртане на екрана, където Android просто създава отново Activity с нова ориентация, сгъваемите устройства въвеждат напълно нови сценарии. Позата HALF_OPENED позволява на приложението да работи на половин екран, а FLAT — в напълно разгънат таблетен режим. Без поддръжка на Screen Continuity всяка промяна на позата нулира интерфейса до началното състояние.
Според Google I/O 2024, повече от 62% от потребителите на сгъваеми устройства са се сблъсквали с приложения, които неправилно обработват превключването между състояния. Screen Continuity решава този проблем на ниво API, предоставяйки на разработчика готови инструменти за запазване и възстановяване на UI.
Jetpack WindowManager дефинира три основни пози на сгъваемото устройство чрез класа FoldingFeature. Всяка поза съответства на определена физическа позиция на пантата и изисква специална обработка на интерфейса.
Устройството е под ъгъл от 30 до 160 градуса. Екранът е разделен на две логически области. Приложението може да показва съдържание на горната половина и контролни елементи на долната половина. Tabletop режим за видеообаждания и медийни плейъри използва точно тази поза.
Устройството е отворено на 180 градуса, образувайки един голям екран. Приложението преминава в таблетен режим с увеличено работно пространство. В тази поза се препоръчва показване на многопанелно оформление с навигационна лента и подробно съдържание едно до друго.
Устройството стои на повърхност под ъгъл около 120 градуса. Долната половина на екрана служи като сензорен панел или клавиатура. Touchpad режим в тази поза позволява емулиране на тракпад на долната част на екрана.
Android обработва промяната на конфигурацията на сгъваемото устройство чрез механизма configuration changes. Когато потребителят разгъне телефона, системата регистрира промяната на размера на прозореца и стартира стандартния цикъл на повторно създаване на Activity. Screen Continuity прихваща този процес и запазва ключовите данни.
Основният метод за запазване на състояние е onRetainNonConfigurationInstance, който се извиква преди унищожаването на Activity. Разработчикът запазва в него модела на данни, позицията на списъка и текущия навигационен екран. След повторно създаване Activity получава тези данни чрез getLastNonConfigurationInstance и възстановява UI точно до момента на сгъване.
За Fragments механизмът е имплементиран чрез setRetainInstance(true), който предотвратява унищожаването на fragment при промяна на конфигурацията. В Jetpack Compose се използва rememberSaveable, който автоматично запазва състоянието при промяна на 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 версия 1.1+ включва класа ScreenContinuityController, който предоставя готови механизми за управление на непрекъснатостта на екрана. API автоматично обработва промяната на позата и уведомява приложението чрез callback интерфейси.
Централен клас, който регистрира слушатели за промяна на позата. registerContinuityListener приема callback, който се задейства при всяко преминаване между състояния на сгъваемото устройство. Контролерът също предоставя информация за текущата поза чрез метода getCurrentFoldingFeature.
Помощен клас за преобразуване на данни от FoldingFeature в състояния, разбираеми за приложението. FoldingFeatureAdapter нормализира координатите на пантата и определя дали текущата поза е HALF_OPENED, FLAT или TABLE_TOP. Това спестява на разработчика ръчно изчисляване на ъгли и прагови стойности.
За Compose приложения WindowManager предоставя WindowSizeClass и модификатори, които отчитат сгъването. Компонентът BoxWithConstraints се адаптира към промените на размерите на екрана в реално време без повторно създаване на Activity. Compose автоматично задейства рекомпозиция при промяна на 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 с поддръжка на Screen Continuity. MainActivity обработва три сценария: сгъване, разгъване и полуотворено състояние. Данните се запазват чрез onRetainNonConfigurationInstance и се възстановяват при повторно създаване.
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, който съхранява списъка с елементи и позицията на превъртане. Activity го запазва преди повторно създаване и го възстановява веднага след извикването на onCreate. Контролерът на WindowManager се абонира за промени на позата и превключва оформлението между режими.
Android Studio предоставя емулатор на сгъваемо устройство с поддръжка на всички три пози. За тестване на Screen Continuity е достатъчно да създадете виртуално устройство от тип Pixel Fold или Samsung Galaxy Z Fold и да превключвате позата чрез контролния панел на емулатора.
Създайте AVD с категория Foldable и изберете резолюция на 7,6-инчов екран. В разширените контроли на емулатора отворете раздела Folding Postures и превключвайте между позите. Всяко превключване задейства configuration change, който трябва да бъде правилно обработен от приложението.
На реално устройство (Galaxy Z Fold 5, Pixel Fold) тестването се извършва чрез физическо разгъване. Режимите Samsung DeX и Multi-Window също активират непрекъснатостта. За отстраняване на грешки използвайте ADB командата adb shell dumpsys window policy, която показва текущото състояние на сгъване.
Основните грешки — загуба на състоянието на RecyclerView, нулиране на текст в текстови полета и затваряне на диалогови прозорци. ViewModel решава тези проблеми, като съхранява данни в паметта независимо от жизнения цикъл на Activity. Също така е важно да анотирате Activity в манифеста с параметъра android:configChanges, ако приложението обработва промените ръчно.
<!-- AndroidManifest.xml -->
@android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"
Често задавани въпроси
Screen Continuity запазва състоянието при физическа промяна на размера на екрана, а не само при завъртане. Обикновеният onSaveInstanceState не гарантира запазване при превключване на позите на сгъваемото устройство, докато ScreenContinuityController обработва именно този сценарий.
Всички сгъваеми устройства с Android 10+ и услуги на Google Play. Поддръжката е включена в Pixel Fold, серията Galaxy Z Fold, Huawei Mate X, Oppo Find N и OnePlus Open. За работа е необходим Jetpack WindowManager версия 1.1 и по-висока.
Jetpack Compose поддържа Screen Continuity чрез rememberSaveable и WindowSizeClass. Композицията автоматично реагира на промяна на WindowMetrics, а rememberSaveable запазва състоянието между рекомпозициите. Модификаторът onSizeChanged позволява проследяване на промените на размерите в реално време.
При разгъване или сгъване на устройството Activity се създава отново без запазване на състоянието. Потребителят губи въведените данни, превъртането се нулира, отворените диалогови прозорци се затварят. Това води до негативни отзиви и спад на рейтинга на приложението в Google Play.
Android Emulator поддържа симулация на сгъваеми устройства. Създайте AVD от тип Pixel Fold, отворете Extended Controls и изберете раздела Folding Postures. Превключването на позите задейства configuration change, позволявайки тестване на запазване на състоянието без физическо устройство.
Обобщение
Ще разработим мобилно приложение под ключ
IT Sectr създава iOS и Android приложения за стартъпи и бизнеси от 2017 г. Ще ви консултираме и ще предложим най-доброто решение.
Прочетете също