يواجه المطوّرون غالبًا صعوبات فريدة عند إنشاء تطبيقات للأجهزة القابلة للطي، خاصةً الأجهزة مثل Samsung Trifold أو Pixel Fold الأصلي الذي يفتح في الوضع الأفقي (rotation_0 = landscape). تشمل أخطاء المطوّرين ما يلي:
- افتراضات خاطئة بشأن اتجاه الجهاز
- حالات الاستخدام التي يتم تجاهلها
- تعذُّر إعادة احتساب القيم أو تخزينها مؤقتًا عند إجراء تغييرات في الإعدادات
تشمل المشاكل المحدّدة المتعلّقة بالجهاز ما يلي:
- عدم تطابق الاتجاه الطبيعي للجهاز بين الشاشة الخارجية والشاشة الداخلية (افتراضات تستند إلى rotation_0 = الوضع العمودي)، ما يؤدي إلى تعذُّر تشغيل التطبيقات عند طي الجهاز وفتحه
- كثافات الشاشة المختلفة والتعامل غير الصحيح مع تغيير إعدادات الكثافة
- مشاكل في معاينة الكاميرا بسبب اعتماد أداة الاستشعار في الكاميرا على الاتجاه الطبيعي
لتقديم تجربة مستخدم عالية الجودة على الأجهزة القابلة للطي، ركِّز على المجالات المهمة التالية:
- تحديد اتجاه التطبيق استنادًا إلى مساحة الشاشة الفعلية التي يشغلها التطبيق، وليس الاتجاه الفعلي للجهاز
- تعديل معاينات الكاميرا لإدارة اتجاه الجهاز ونِسب العرض إلى الارتفاع بشكل صحيح وتجنُّب المعاينات المنحرفة ومنع الصور الممدودة أو التي تم اقتصاصها
- الحفاظ على استمرارية التطبيق أثناء طي الجهاز أو فتحه من خلال الاحتفاظ بالحالة باستخدام
ViewModelأو طرق مشابهة، أو من خلال معالجة تغييرات كثافة الشاشة وتغييرات الاتجاه يدويًا، ما يؤدي إلى تجنُّب إعادة تشغيل التطبيق أو فقدان الحالة - بالنسبة إلى التطبيقات التي تستخدم مستشعرات الحركة، اضبط نظام الإحداثيات ليتوافق مع الاتجاه الحالي للشاشة وتجنَّب الافتراضات المستندة إلى rotation_0 = الوضع العمودي، ما يضمن تفاعلات دقيقة للمستخدم.
إنشاء تطبيق متوافق
إذا كان تطبيقك متكيّفًا ويتوافق مع المستوى المحسّن (المستوى 2) الموضّح في إرشادات جودة التطبيقات المتكيّفة، من المفترض أن يعمل التطبيق بشكل جيد على الأجهزة القابلة للطي. في ما عدا ذلك، قبل إعادة التحقّق من التفاصيل المحدّدة للأجهزة القابلة للطي ثلاثية الطيات والأجهزة القابلة للطي ذات الوضع الأفقي، راجِع مفاهيم التطوير الأساسية المتوافقة مع الأجهزة القابلة للطي في Android.
التنسيقات التكيّفية
يجب أن تتعامل واجهة المستخدم مع أحجام الشاشات المختلفة، بالإضافة إلى التغييرات في نسبة العرض إلى الارتفاع في الوقت الفعلي، مثل فتح الجهاز واستخدام وضع النوافذ المتعددة أو وضع النوافذ على سطح المكتب. اطّلِع على لمحة عن التصاميم التكيّفية للحصول على مزيد من الإرشادات حول كيفية:
- تصميم التنسيقات التكيّفية وتنفيذها
- ضبط التنقّل الأساسي في تطبيقك استنادًا إلى حجم النافذة
- استخدام فئات حجم النافذة لتكييف واجهة المستخدم في تطبيقك
- تسهيل تنفيذ التصاميم الأساسية، مثل عرض على شكل قائمة مع تفاصيل، باستخدام واجهات برمجة تطبيقات Jetpack
فئات حجم النافذة
يمكن للأجهزة القابلة للطي، بما في ذلك الأجهزة القابلة للطي في الوضع الأفقي والأجهزة الثلاثية الطي، التبديل بين فئات أحجام النوافذ المضغوطة والمتوسطة والموسّعة على الفور. يضمن فهم هذه الفئات وتنفيذها عرض تطبيقك لمكوّنات التنقّل وكثافة المحتوى المناسبة لحالة الجهاز الحالية.
يستخدم المثال التالي مكتبة Material 3 المتكيّفة لتحديد المساحة المتاحة للتطبيق من خلال استدعاء الدالة currentWindowAdaptiveInfo() أولاً، ثم استخدام التصاميم المناسبة لفئات أحجام النوافذ الثلاث:
val adaptiveInfo = currentWindowAdaptiveInfo()
val windowSizeClass = adaptiveInfo.windowSizeClass
when {
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_EXPANDED_LOWER_BOUND) -> // Expanded
windowSizeClass.isWidthAtLeastBreakpoint(WIDTH_DP_MEDIUM_LOWER_BOUND) -> // Medium
else -> // Compact
}
لمزيد من المعلومات، يُرجى الاطّلاع على استخدام فئات حجم النافذة.
جودة التطبيقات التكيّفية
يضمن الالتزام بالمستوى 2 (التطبيق المتكيّف المحسَّن) أو المستوى 1 (التطبيق المتكيّف المميّز) من إرشادات جودة التطبيقات المتكيّفة أن يقدّم تطبيقك تجربة مستخدم جذابة على الأجهزة الثلاثية الطي والأجهزة القابلة للطي في الوضع الأفقي وغيرها من الأجهزة ذات الشاشات الكبيرة. تتضمّن الإرشادات عمليات تحقّق مهمة على مستويات متعددة من الأداء، وذلك للانتقال من الأداء المتكيّف إلى تجربة متميّزة.
الإصدار 16 من نظام التشغيل Android والإصدارات الأحدث
بالنسبة إلى التطبيقات التي تستهدف الإصدار Android 16 (مستوى واجهة برمجة التطبيقات 36) والإصدارات الأحدث، يتجاهل النظام قيود الاتجاه وتغيير الحجم ونسبة العرض إلى الارتفاع على الشاشات التي يبلغ عرضها الأصغر 600 وحدة بكسل مستقل الكثافة أو أكثر. تتوسّع التطبيقات لتملأ نافذة العرض بأكملها، بغض النظر عن نسبة العرض إلى الارتفاع أو اتجاه الشاشة المفضّل لدى المستخدم، ولم يعُد يتم استخدام وضع التوافق لإضافة إطارات سوداء.
اعتبارات خاصة
تتضمّن الأجهزة اللوحية ثلاثية الطيّ والهواتف القابلة للطي ذات الوضع الأفقي سلوكيات فريدة للأجهزة تتطلّب معالجة خاصة، لا سيما فيما يتعلق بأجهزة الاستشعار ومعاينة الكاميرا واستمرار الإعدادات (الاحتفاظ بالحالة عند الطي أو الفتح أو تغيير الحجم).
معاينة الكاميرا
من المشاكل الشائعة في الأجهزة القابلة للطي في الوضع الأفقي أو في حسابات نسبة العرض إلى الارتفاع (في سيناريوهات مثل النوافذ المتعددة أو العرض في نافذة على الكمبيوتر أو الشاشات المتصلة) ظهور معاينة الكاميرا بشكل ممدود أو جانبي أو مقصوص أو تم تدويرها.
الافتراضات غير المتطابقة
تحدث هذه المشكلة غالبًا على الأجهزة ذات الشاشات الكبيرة والأجهزة القابلة للطي لأنّ التطبيقات يمكن أن تفترض علاقات ثابتة بين ميزات الكاميرا، مثل نسبة العرض إلى الارتفاع واتجاه المستشعر، وميزات الجهاز، مثل اتجاه الجهاز والاتجاه الطبيعي.
وتتحدى أشكال الأجهزة الجديدة هذا الافتراض. يمكن لجهاز قابل للطي تغيير حجم الشاشة ونسبة العرض إلى الارتفاع بدون أن يؤدي ذلك إلى تغيير اتجاه الجهاز. على سبيل المثال، يؤدي فتح الجهاز إلى تغيير نسبة العرض إلى الارتفاع، ولكن إذا لم يدوّر المستخدم الجهاز، سيبقى اتجاهه كما هو. إذا افترض أحد التطبيقات أنّ نسبة العرض إلى الارتفاع مرتبطة بتدوير الجهاز، قد يؤدي ذلك إلى تدوير معاينة الكاميرا أو تغيير حجمها بشكل غير صحيح. قد يحدث الأمر نفسه إذا افترض أحد التطبيقات أنّ اتجاه مستشعر الكاميرا يتطابق مع اتجاه الجهاز في الوضع العمودي، وهو ما لا ينطبق دائمًا على الأجهزة القابلة للطي في الوضع الأفقي.
الحلّ 1: Jetpack CameraX (الأفضل)
أبسط الحلول وأكثرها فعالية هو استخدام مكتبة Jetpack CameraX. تم تصميم عنصر في واجهة المستخدم
PreviewView للتعامل مع جميع تعقيدات المعاينة
تلقائيًا:
- تعدّل
PreviewViewبشكل صحيح اتجاه جهاز الاستشعار وتدوير الجهاز وتغيير حجمه. - تحافظ هذه السمة على نسبة العرض إلى الارتفاع لصورة الكاميرا، وعادةً ما يتم ذلك من خلال توسيط الصورة واقتصاصها (FILL_CENTER).
- يمكنك ضبط نوع المقياس على
FIT_CENTERلتضمين معاينة في إطار إذا لزم الأمر.
لمزيد من المعلومات، راجِع تنفيذ معاينة في مستندات CameraX.
الحلّ 2: CameraViewfinder
إذا كنت تستخدم قاعدة رموز برمجية حالية في Camera2، فإنّ مكتبة CameraViewfinder (متوافقة مع الأنظمة القديمة حتى مستوى واجهة برمجة التطبيقات 21) هي حلّ حديث آخر. ويسهّل عرض خلاصة الكاميرا باستخدام TextureView أو SurfaceView، كما يطبّق جميع عمليات التحويل اللازمة (نسبة العرض إلى الارتفاع، والحجم، والتدوير) نيابةً عنك.
لمزيد من المعلومات، يُرجى الاطّلاع على مشاركة المدونة تقديم ميزة "نافذة عرض الكاميرا" ودليل المطوّر معاينة الكاميرا.
الحلّ 3: استخدام Camera2 يدويًا
إذا تعذّر عليك استخدام CameraX أو CameraViewfinder، عليك احتساب الاتجاه ونسبة العرض إلى الارتفاع يدويًا والتأكّد من تعديل العمليات الحسابية عند كل تغيير في الإعدادات:
- احصل على اتجاه أداة الاستشعار في الكاميرا (على سبيل المثال، 0 أو 90 أو 180 أو 270 درجة)
من
CameraCharacteristics. - الحصول على اتجاه تدوير الشاشة الحالي للجهاز (على سبيل المثال، 0 أو 90 أو 180 أو 270 درجة)
- استخدِم هاتين القيمتين لتحديد عمليات التحويل اللازمة لـ
SurfaceViewأوTextureView. - تأكَّد من أنّ نسبة العرض إلى الارتفاع في الناتج
Surfaceتتطابق مع نسبة العرض إلى الارتفاع في معاينة الكاميرا لتجنُّب التشويش. - قد يكون تطبيق الكاميرا قيد التشغيل في جزء من الشاشة، إما في وضع النوافذ المتعددة أو وضع العرض في نافذة على سطح المكتب أو على شاشة عرض متصلة. لهذا السبب، يجب عدم استخدام حجم الشاشة لتحديد أبعاد عدسة الكاميرا، بل يجب استخدام مقاييس النافذة بدلاً من ذلك.
لمزيد من المعلومات، يُرجى الاطّلاع على دليل المطوّرين معاينة الكاميرا والفيديو تطبيق الكاميرا على أشكال مختلفة.
الحلّ 4: تنفيذ إجراءات أساسية للكاميرا باستخدام intent
إذا لم تكن بحاجة إلى العديد من ميزات الكاميرا، يمكنك تنفيذ إجراءات أساسية، مثل التقاط صورة أو فيديو باستخدام تطبيق الكاميرا التلقائي على الجهاز. لست بحاجة إلى الدمج مع مكتبة كاميرا، بل يمكنك استخدام Intent.
لمزيد من المعلومات، يُرجى الاطّلاع على أهداف الكاميرا.
الإعداد والاستمرارية
توفّر الأجهزة القابلة للطي تنوّعًا أكبر في واجهة المستخدم، ولكنها قد تتطلّب إجراء تغييرات في الإعدادات أكثر من الأجهزة غير القابلة للطي. يجب أن يدير تطبيقك تغييرات الضبط هذه ومجموعاتها، مثل تدوير الجهاز والطي/الفتح وتغيير حجم النافذة في وضع النوافذ المتعددة أو وضع سطح المكتب، مع الاحتفاظ بحالة التطبيق أو استعادتها. على سبيل المثال، يجب أن تحافظ التطبيقات على الاستمرارية التالية:
- حالة التطبيق بدون حدوث أعطال أو تغييرات مزعجة للمستخدمين (على سبيل المثال، عند تبديل الشاشات أو إرسال التطبيق إلى الخلفية)
- موضع التمرير للحقول القابلة للتمرير
- النص الذي يتم إدخاله في حقول النص وحالة لوحة المفاتيح
- موضع تشغيل الوسائط حتى يتم استئناف التشغيل من حيث توقّف عند بدء تغيير الإعدادات
تشمل تغييرات الإعدادات التي يتم تشغيلها بشكل متكرّر screenSize وsmallestScreenSize وscreenLayout وorientation وdensity وfontScale وtouchscreen وkeyboard.
راجِع android:configChanges والتعامل مع تغييرات الإعدادات. للحصول على معلومات إضافية حول إدارة حالة التطبيق، اطّلِع على حفظ حالات واجهة المستخدم.
تغييرات إعدادات الكثافة
قد تتضمّن الشاشتان الخارجية والداخلية للأجهزة القابلة للطي ثلاثيًا والأجهزة القابلة للطي في الوضع الأفقي كثافات بكسل مختلفة. لذلك، تتطلّب إدارة تغيير الإعدادات
لـ density المزيد من الاهتمام. يعيد نظام التشغيل Android عادةً تشغيل النشاط
عندما تتغير كثافة العرض، ما قد يؤدي إلى فقدان البيانات. لمنع النظام من إعادة تشغيل النشاط، عليك تعريف معالجة الكثافة في ملف البيان وإدارة تغيير الإعدادات آليًا في تطبيقك.
إعداد ملف AndroidManifest.xml
density: تحدّد ما إذا كان التطبيق سيتعامل مع تغيير كثافة الشاشة- تغييرات أخرى في الإعدادات: من المفيد أيضًا الإشارة إلى التغييرات الأخرى التي تحدث بشكل متكرر في الإعدادات، مثل
screenSizeوorientationوkeyboardHiddenوfontScaleوما إلى ذلك.
يؤدي تحديد الكثافة (وغيرها من تغييرات الإعدادات) إلى منع النظام من إعادة تشغيل النشاط، ويتم بدلاً من ذلك استدعاء onConfigurationChanged().
تنفيذ onConfigurationChanged()
عند حدوث تغيير في الكثافة، عليك تعديل الموارد (مثل إعادة تحميل الصور النقطية أو إعادة احتساب أحجام التنسيق) في دالة معاودة الاتصال:
- تأكَّد من تغيير DPI إلى
newConfig.densityDpi - إعادة ضبط طرق العرض المخصّصة والعناصر القابلة للرسم المخصّصة وما إلى ذلك على الكثافة الجديدة
عناصر الموارد المطلوب معالجتها
- مصدر الصورة: استبدِل الصور النقطية والصور القابلة للرسم بموارد خاصة بالكثافة، أو اضبط المقياس مباشرةً
- وحدة التنسيق (تحويل dp إلى px): إعادة احتساب حجم العرض والهامش والحشو
- حجم الخط والنص: إعادة تطبيق حجم النص بوحدة sp
- رسم
View/Canvasمخصّص: تعديل القيم المستندة إلى وحدات البكسل المستخدَمة لرسمCanvas
تحديد اتجاه التطبيق
لا تعتمد أبدًا على تدوير الجهاز الفعلي عند إنشاء تصميم متجاوب، لأنّه سيتم تجاهله على الأجهزة ذات الشاشات الكبيرة، وقد يكون اتجاه التطبيق في وضع النوافذ المتعددة مختلفًا عن اتجاه الجهاز. بدلاً من ذلك، استخدِم Configuration.orientation أو WindowMetrics لتحديد ما إذا كان تطبيقك معروضًا حاليًا بالاتجاه الأفقي أو العمودي استنادًا إلى حجم النافذة.
الحلّ 1: استخدام Configuration.orientation
تحدّد هذه السمة اتجاه عرض تطبيقك حاليًا.
الحلّ 2: استخدام WindowMetrics#getBounds()
يمكنك الحصول على حدود العرض الحالية للتطبيق والتحقّق من عرضه وارتفاعه لتحديد اتجاهه.
إذا كنت بحاجة إلى حصر اتجاه التطبيق على الهواتف (أو الشاشات الخارجية للأجهزة القابلة للطي) وليس على الأجهزة ذات الشاشات الكبيرة، يمكنك الاطّلاع على حصر اتجاه التطبيق على الهواتف.
أوضاع الجهاز وأساليب العرض
تتوافق الأجهزة القابلة للطي في الوضع العمودي والأفقي مع أوضاع الاستخدام، مثل وضع "الطاولة" وHALF_OPENED. مع ذلك، لا يمكن استخدام الحوامل الثلاثية الطيّ HALF_OPENED لأنّها لا تتيح وضع الجهاز على الشاشة المسطحة. في المقابل، توفّر الأجهزة الثلاثية الطي شاشة أكبر لتوفير تجربة فريدة للمستخدم عند فتحها بالكامل.
لتمييز تطبيقك على الأجهزة القابلة للطي التي تتوافق مع HALF_OPENED، استخدِم واجهات برمجة التطبيقات Jetpack WindowManager، مثل FoldingFeature.
يمكنك الاطّلاع على مزيد من المعلومات حول أوضاع الأجهزة القابلة للطي وحالاتها ومدى توافقها مع معاينة الكاميرا في أدلة المطوّرين التالية:
توفّر الأجهزة القابلة للطي تجارب مشاهدة فريدة. يتيح لك وضع الشاشة الخلفية ووضع الشاشة المزدوجة إنشاء ميزات عرض خاصة للأجهزة القابلة للطي، مثل معاينة صور السيلفي بالكاميرا الخلفية والعرض المتزامن ولكن المختلف على الشاشتين الداخلية والخارجية. لمزيد من المعلومات، يُرجى الاطّلاع على:
قفل اتجاه الشاشة على اتجاه جهاز الاستشعار الطبيعي
بالنسبة إلى حالات استخدام محدّدة جدًا، وخاصةً التطبيقات التي تحتاج إلى الاستحواذ على الشاشة بأكملها بغض النظر عن حالة طي الجهاز، تتيح لك العلامة nosensor قفل التطبيق على الاتجاه الطبيعي للجهاز. على سبيل المثال، على هاتف Pixel Fold، يكون اتجاه الجهاز الطبيعي عند طيّه هو الوضع العمودي، بينما يكون اتجاهه الطبيعي عند فتحه هو الوضع الأفقي. تؤدي إضافة العلامة nosensor إلى فرض قفل التطبيق على الوضع العمودي عند تشغيله على الشاشة الخارجية، وعلى الوضع الأفقي عند تشغيله على الشاشة الداخلية.
<activity
android:name=".MainActivity"
android:screenOrientation="nosensor">
الألعاب وإعادة ربط أجهزة استشعار الواقع الممتد
بالنسبة إلى الألعاب وتطبيقات الواقع الممتد، يتم توفير بيانات أجهزة الاستشعار الأولية (مثل الجيروسكوب أو مقياس التسارع) في نظام الإحداثيات الثابت بالجهاز. إذا أدار المستخدم الجهاز لتشغيل لعبة في الوضع الأفقي، لن تدور محاور أداة الاستشعار مع الشاشة، ما يؤدي إلى عدم صحة عناصر التحكّم في اللعبة.
لحلّ هذه المشكلة، تحقَّق من قيمة Display.getRotation() الحالية وأعِد ربط المحاور وفقًا لذلك:
- الدوران 0: x=x, y=y
- الاستدارة بمقدار 90 درجة: x=-y, y=x
- الدوران بمقدار 180 درجة: x=-x, y=-y
- التدوير بمقدار 270 درجة: x=y, y=-x
بالنسبة إلى متجهات الدوران (المستخدَمة في البوصلة أو تطبيقات الواقع الممتد)، استخدِم الدالة SensorManager.remapCoordinateSystem() لربط اتجاه عدسة الكاميرا أو أعلى الشاشة بالمحاور الجديدة استنادًا إلى الدوران الحالي.
توافق التطبيقات
يجب أن تتّبع التطبيقات إرشادات جودة التطبيقات لضمان التوافق مع جميع أشكال الأجهزة والشاشات المتصلة. إذا لم يتمكّن أحد التطبيقات من الالتزام بالإرشادات، يمكن لمصنّعي الأجهزة تنفيذ إجراءات توافق، ولكن قد يؤدي ذلك إلى تدهور تجربة المستخدم.
للحصول على معلومات إضافية، راجِع القائمة الشاملة لحلول التوافق المتوفّرة في النظام الأساسي، وخاصةً تلك المتعلّقة بمعاينة الكاميرا وعمليات الإلغاء والتغييرات في واجهة برمجة التطبيقات Android 16 التي قد تغيّر سلوك تطبيقك.
لمزيد من المعلومات حول إنشاء تطبيقات متجاوبة، يُرجى الاطّلاع على إرشادات جودة التطبيقات المتجاوبة.