Screen Continuity — هي آلية في أندرويد تضمن انتقالاً سلساً للتطبيق بين الحالتين المطوية والمفتوحة للجهاز القابل للطي. عند الفتح، تغير الشاشة أبعادها الفيزيائية، ويعيد النظام تشغيل Activity بإعدادات جديدة. وفقاً لـ Google Developer, 2025، فإن المعالجة الصحيحة للاستمرارية تحسن تجربة المستخدم بنسبة 40% وتقلل الشكاوى من فقدان الحالة. API ScreenContinuity هو جزء من Jetpack WindowManager ابتداءً من الإصدار 1.1 ويسمح للمطور بإدارة دورة الحياة عند تغير وضعية الجهاز.
النقاط الرئيسية
Screen Continuity هي آلية في أندرويد تحافظ على حالة Activity عند تغير التكوين الفيزيائي للشاشة على الأجهزة القابلة للطي. عندما يفتح المستخدم الهاتف أو يطويه، قد يعيد النظام تشغيل Activity بأبعاد نافذة جديدة. تمنع الاستمرارية فقدان البيانات المدخلة وموضع التمرير والشاشة الحالية.
على عكس التدوير البسيط للشاشة حيث يعيد أندرويد إنشاء Activity باتجاه جديد فقط، تقدم الأجهزة القابلة للطي سيناريوهات جديدة تماماً. وضع HALF_OPENED يسمح للتطبيق بالعمل على نصف شاشة، بينما FLAT يعمل في وضع الجهاز اللوحي مفتوحاً بالكامل. بدون دعم Screen Continuity، كل تغيير في الوضع يعيد الواجهة إلى حالتها الأولية.
وفقاً لـ Google I/O 2024، أكثر من 62% من مستخدمي الأجهزة القابلة للطي واجهوا تطبيقات تتعامل بشكل غير صحيح مع تبديل الحالة. Screen Continuity يحل هذه المشكلة على مستوى API، مزوداً المطور بأدوات جاهزة لحفظ واستعادة واجهة المستخدم.
Jetpack WindowManager يحدد ثلاثة أوضاع أساسية للأجهزة القابلة للطي من خلال فئة FoldingFeature. كل وضع يتوافق مع موضع مادي معين للمفصلة ويتطلب معالجة خاصة للواجهة.
الجهاز بزاوية من 30 إلى 160 درجة. الشاشة مقسمة إلى منطقتين منطقيتين. يمكن للتطبيق عرض المحتوى على النصف العلوي وعناصر التحكم على النصف السفلي. وضع الطاولة لمكالمات الفيديو ومشغلات الوسائط يستخدم هذا الوضع.
الجهاز مفتوح 180 درجة، مشكلاً شاشة واحدة كبيرة. يتحول التطبيق إلى وضع الجهاز اللوحي بمساحة عمل موسعة. في هذا الوضع، يُنصح بإظهار تخطيط متعدد الأجزاء مع لوحة تنقل ومحتوى مفصل جنباً إلى جنب.
الجهاز يقف على سطح بزاوية حوالي 120 درجة. النصف السفلي من الشاشة يعمل كلوحة لمس أو لوحة مفاتيح. وضع لوحة اللمس في هذا الوضع يسمح بمحاكاة لوحة التتبع على الجزء السفلي من الشاشة.
أندرويد يتعامل مع تغييرات تكوين الجهاز القابل للطي من خلال آلية configuration changes. عندما يفتح المستخدم الهاتف، يكتشف النظام تغيير حجم النافذة ويبدأ دورة إعادة إنشاء Activity القياسية. Screen Continuity يعترض هذه العملية ويحفظ البيانات الرئيسية.
الطريقة الرئيسية لحفظ الحالة هي onRetainNonConfigurationInstance، والتي تُستدعى قبل تدمير Activity. المطور يحفظ فيها نموذج البيانات وموضع القائمة وشاشة التنقل الحالية. بعد إعادة الإنشاء، تتلقى Activity هذه البيانات عبر getLastNonConfigurationInstance وتستعيد الواجهة تماماً كما كانت قبل الطي.
بالنسبة لـ 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 controller في الاشتراك بتغييرات الوضع ويبدل التخطيط بين الأوضاع.
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.
محاكي أندرويد يدعم محاكاة الأجهزة القابلة للطي. أنشئ AVD من نوع Pixel Fold، افتح Extended Controls واختر علامة التبويب Folding Postures. تبديل الأوضاع يفعّل configuration change، مما يسمح باختبار الحفاظ على الحالة بدون جهاز فعلي.
الخلاصة
سنقوم بتطوير تطبيق جوال جاهز
تقدم IT Sectr تطبيقات iOS وAndroid للشركات الناشئة والشركات منذ عام 2017. سوف نقدم لك النصح ونقترح أفضل حل.