يتيح دعم أحجام العرض المختلفة الوصول إلى تطبيقك من خلال أوسع مجموعة من الأجهزة وأكبر عدد من المستخدمين.
لدعم أكبر عدد ممكن من أحجام العرض، سواء كانت شاشات أجهزة مختلفة أو نوافذ تطبيقات مختلفة في وضع النوافذ المتعدّدة، صمِّم تنسيقات تطبيقك لتكون متجاوبة وتكيُّفية. توفّر التنسيقات المتجاوبة/التكيُّفية تجربة مستخدم محسّنة بغض النظر عن حجم العرض، ما يتيح لتطبيقك استيعاب الهواتف والأجهزة اللوحية والأجهزة القابلة للطي وأجهزة ChromeOS والاتجاهَين العمودي والأفقي وإعدادات العرض القابلة لتغيير الحجم، مثل وضع تقسيم الشاشة والعرض في نافذة على الكمبيوتر.
تتغيّر التنسيقات المتجاوبة/التكيُّفية استنادًا إلى مساحة العرض المتاحة. تتراوح التغييرات بين تعديلات صغيرة على التنسيق تملأ المساحة (التصميم المتجاوب) واستبدال تنسيق بآخر بالكامل حتى يتمكّن تطبيقك من استيعاب أحجام العرض المختلفة على أفضل وجه (التصميم التكيُّفي).
باعتبارها مجموعة أدوات تعريفية لواجهة المستخدم، تُعدّ Jetpack Compose مثالية لتصميم التنسيقات وتنفيذها، والتي تتغيّر ديناميكيًا لعرض المحتوى بشكل مختلف على أحجام العرض المختلفة.
توضيح التغييرات الكبيرة في التنسيق للعناصر المركّبة على مستوى المحتوى
تشغل العناصر المركّبة على مستوى التطبيق وعلى مستوى المحتوى كل مساحة العرض المتاحة لتطبيقك. بالنسبة إلى هذه الأنواع من العناصر المركّبة، قد يكون من المنطقي تغيير التنسيق العام لتطبيقك على الشاشات الكبيرة.
تجنَّب استخدام قيم الأجهزة المادية لاتخاذ قرارات بشأن التنسيق. قد يكون من المغري اتخاذ قرارات استنادًا إلى قيمة ملموسة ثابتة (هل الجهاز جهاز لوحي؟ هل تتضمّن الشاشة المادية نسبة عرض إلى ارتفاع معيّنة؟)، ولكن قد لا تكون الإجابات عن هذه الأسئلة مفيدة لتحديد المساحة المتاحة لواجهة المستخدم.
على الأجهزة اللوحية، قد يتم تشغيل تطبيق في وضع النوافذ المتعدّدة، ما يعني أنّ التطبيق قد يقسّم الشاشة مع تطبيق آخر. في وضع العرض في نافذة على الكمبيوتر أو على ChromeOS، قد يكون التطبيق في نافذة قابلة لتغيير الحجم. قد يكون هناك أكثر من شاشة مادية واحدة، كما هو الحال في الأجهزة القابلة للطي. في كل هذه الحالات، لا يكون حجم الشاشة المادية ذا صلة بتحديد كيفية عرض المحتوى.
بدلاً من ذلك، اتّخِذ قرارات استنادًا إلى الجزء الفعلي من الشاشة المخصّص لـ تطبيقك والموصوف بمقاييس النافذة الحالية التي توفّرها مكتبة Jetpack WindowManager. للاطّلاع على مثال حول كيفية استخدام WindowManager في تطبيق Compose، راجِع نموذج JetNews.
يؤدي تكييف تنسيقاتك مع مساحة العرض المتاحة أيضًا إلى تقليل مقدار المعالجة الخاصة اللازمة لدعم منصات مثل ChromeOS وعوامل شكل مثل الأجهزة اللوحية والأجهزة القابلة للطي.
بعد تحديد مقاييس المساحة المتاحة لتطبيقك، حوِّل الحجم الأولي إلى فئة حجم النافذة كما هو موضّح في مقالة استخدام فئات حجم النافذة. فئات حجم النافذة هي نقاط توقف مصمّمة لتحقيق التوازن بين بساطة منطق التطبيق ومرونته لتحسين تطبيقك لمعظم أحجام العرض.
تشير فئات حجم النافذة إلى النافذة الإجمالية لتطبيقك، لذا استخدِم الفئات لاتخاذ قرارات بشأن التنسيق تؤثّر في تنسيق تطبيقك العام. يمكنك تمرير فئات حجم النافذة كحالة، أو يمكنك تنفيذ منطق إضافي لإنشاء حالة مشتقة لتمريرها إلى العناصر المركّبة المتداخلة.
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo(supportLargeAndXLargeWidth = true).windowSizeClass ) { // Decide whether to show the top app bar based on window size class. val showTopAppBar = windowSizeClass.isHeightAtLeastBreakpoint(WindowSizeClass.HEIGHT_DP_MEDIUM_LOWER_BOUND) // MyScreen logic is based on the showTopAppBar boolean flag. MyScreen( showTopAppBar = showTopAppBar, /* ... */ ) }
يؤدي استخدام نهج متعدد الطبقات إلى حصر منطق حجم العرض في موقع واحد بدلاً من توزيعه على مستوى تطبيقك في العديد من المواقع التي يجب أن تظل متزامنة. ينتج عن الموقع الواحد حالة يمكن تمريرها بشكل صريح إلى العناصر المركّبة الأخرى تمامًا مثل أي حالة أخرى للتطبيق. يؤدي تمرير الحالة بشكل صريح إلى تبسيط العناصر المركّبة الفردية لأنّ العناصر المركّبة تأخذ فئة حجم النافذة أو الإعدادات المحدّدة بالإضافة إلى البيانات الأخرى.
العناصر المركّبة المتداخلة المرنة قابلة لإعادة الاستخدام
تكون العناصر المركّبة أكثر قابلية لإعادة الاستخدام عندما يمكن وضعها في مجموعة متنوعة من المواقع. إذا كان يجب وضع عنصر مركّب في موقع معيّن بحجم معيّن، فمن غير المرجّح أن يكون العنصر المركّب قابلاً لإعادة الاستخدام في سياقات أخرى. يعني هذا أيضًا أنّه يجب على العناصر المركّبة الفردية القابلة لإعادة الاستخدام تجنُّب الاعتماد ضمنيًا على معلومات حجم العرض العامة.
تخيَّل دالة مركّبة متداخلة تنفّذ تنسيق عرض على شكل قائمة مع تفاصيل، وقد تعرض إما لوحة واحدة أو لوحتين جنبًا إلى جنب:
يجب أن يكون قرار عرض على شكل قائمة مع تفاصيل جزءًا من التنسيق العام للتطبيق، لذا يتم تمرير القرار من دالة مركّبة على مستوى المحتوى:
@Composable fun AdaptivePane( showOnePane: Boolean, /* ... */ ) { if (showOnePane) { OnePane(/* ... */) } else { TwoPane(/* ... */) } }
ماذا لو أردت بدلاً من ذلك أن تغيّر دالة مركّبة تنسيقها بشكل مستقل استنادًا إلى مساحة العرض المتاحة، على سبيل المثال، بطاقة تعرض تفاصيل إضافية إذا كانت المساحة تسمح بذلك؟ تريد تنفيذ بعض المنطق استنادًا إلى حجم عرض معيّن، ولكن أي حجم تحديدًا؟
تجنَّب محاولة استخدام حجم الشاشة الفعلي للجهاز. لن يكون هذا الحجم دقيقًا لأنواع الشاشات المختلفة، ولن يكون دقيقًا أيضًا إذا لم يكن التطبيق بملء الشاشة.
بما أنّ العنصر المركّب ليس عنصرًا مركّبًا على مستوى المحتوى، لا تستخدِم مقاييس النافذة الحالية مباشرةً.
إذا تم وضع المكوّن مع مساحة متروكة (مثل الحواف الداخلية)، أو إذا كان التطبيق يتضمّن مكوّنات مثل أشرطة التنقّل أو أشرطة التطبيق، فقد يختلف مقدار مساحة العرض المتاحة للعنصر المركّب اختلافًا كبيرًا عن المساحة الإجمالية المتاحة للتطبيق.
استخدِم العرض الذي يتم منحه فعليًا للدالة المركّبة لعرض نفسها. أمامك خياران للحصول على هذا العرض:
إذا أردت تغيير مكان عرض المحتوى أو كيفية عرضه، استخدِم مجموعة من المعدِّلات أو تنسيقًا مخصّصًا لجعل التنسيق متجاوبًا. يمكن أن يكون هذا بسيطًا مثل جعل عنصر ثانوي يملأ كل المساحة المتاحة، أو ترتيب العناصر الثانوية بعدة أعمدة إذا كانت هناك مساحة كافية.
إذا أردت تغيير ما تعرضه، استخدِم
BoxWithConstraintsكبديل أكثر فعالية.BoxWithConstraintsتوفّر قيودًا على القياس يمكنك استخدامها لاستدعاء عناصر مركّبة مختلفة استنادًا إلى مساحة العرض المتاحة. ومع ذلك، يأتي ذلك على حساب معيّن، لأنّBoxWithConstraintsتؤجّل التركيب حتى مرحلة التنسيق، عندما تكون هذه القيود معروفة، ما يؤدي إلى تنفيذ المزيد من العمل أثناء التنسيق.
@Composable fun Card(/* ... */) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(/* ... */) Title(/* ... */) } } else { Row { Column { Title(/* ... */) Description(/* ... */) } Image(/* ... */) } } } }
إتاحة جميع البيانات لأحجام العرض المختلفة
عند تنفيذ دالة مركّبة تستفيد من مساحة العرض الإضافية، قد يكون من المغري أن تكون فعالاً وتحمِّل البيانات كأثر جانبي لحجم العرض الحالي.
ومع ذلك، يتعارض هذا الإجراء مع مبدأ تدفق البيانات أحادي الاتجاه، حيث يمكن رفع البيانات وتوفيرها للعناصر المركّبة لعرضها بشكل مناسب. يجب توفير بيانات كافية للعنصر المركّب بحيث يكون لديه دائمًا محتوى كافٍ لأي حجم عرض، حتى إذا لم يتم استخدام جزء من المحتوى دائمًا.
@Composable fun Card( imageUrl: String, title: String, description: String ) { BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description(description) } Image(imageUrl) } } } }
استنادًا إلى مثال Card، لاحظ أنّه يتم دائمًا تمرير description إلى Card. على الرغم من أنّ description لا تُستخدَم إلا عندما يسمح العرض بعرضها، فإنّ Card تتطلّب دائمًا description، بغض النظر عن العرض المتاح.
يؤدي تمرير محتوى كافٍ دائمًا إلى تبسيط التنسيقات التكيُّفية من خلال جعلها أقل احتفاظًا بالحالة وتجنُّب إطلاق آثار جانبية عند التبديل بين أحجام العرض (التي قد تحدث بسبب تغيير حجم النافذة أو تغيير الاتجاه أو طي الجهاز وفتحه).
يسمح هذا المبدأ أيضًا بالحفاظ على الحالة عند إجراء تغييرات على التنسيق. من خلال رفع المعلومات التي قد لا يتم استخدامها على جميع أحجام العرض، يمكنك الحفاظ على حالة التطبيق عند تغيير حجم التنسيق.
على سبيل المثال، يمكنك رفع علامة منطقية showMore لكي يتم الحفاظ على حالة التطبيق عندما يؤدي تغيير حجم العرض إلى تبديل التنسيق بين إخفاء المحتوى وعرضه:
@Composable fun Card( imageUrl: String, title: String, description: String ) { var showMore by remember { mutableStateOf(false) } BoxWithConstraints { if (maxWidth < 400.dp) { Column { Image(imageUrl) Title(title) } } else { Row { Column { Title(title) Description( description = description, showMore = showMore, onShowMoreToggled = { newValue -> showMore = newValue } ) } Image(imageUrl) } } } }
مزيد من المعلومات
لمزيد من المعلومات عن التنسيقات التكيُّفية في Compose، اطّلِع على المَراجع التالية:
تطبيقات نموذجية
- CanonicalLayouts هو مستودع لأنماط تصميم مُثبَتة توفّر تجربة مستخدم مثالية على الشاشات الكبيرة
- JetNews يوضّح كيفية تصميم تطبيق يكيّف واجهة المستخدم الخاصة به للاستفادة من مساحة العرض المتاحة
- Reply هو نموذج تكيُّفي لدعم الهواتف، الأجهزة اللوحية والأجهزة القابلة للطي
- Now in Android هو تطبيق يستخدم تنسيقات تكيُّفية لدعم أحجام العرض المختلفة
الفيديوهات