من خلال توفير أحجام شاشات مختلفة، يمكنك إتاحة تطبيقك على أكبر عدد ممكن من الأجهزة وأكبر عدد من المستخدمين.
لتتوافق مع أكبر عدد ممكن من أحجام الشاشات، سواء كانت شاشة الجهاز المختلفة أو نوافذ التطبيق المختلفة في وضع النوافذ المتعددة، يجب تصميم تنسيقات التطبيق بحيث تكون سريعة الاستجابة وقابلة للتكيّف. توفّر التنسيقات السريعة الاستجابة/المتوافقة تجربة محسّنة للمستخدم بغض النظر عن حجم الشاشة، ما يتيح لتطبيقك التوافق مع الهواتف والأجهزة اللوحية والأجهزة القابلة للطي وأجهزة ChromeOS واتجاهَي الشاشة العمودي والمائل وإعدادات الشاشة القابلة للتغيير، مثل وضع شاشة القسمين ووضع النوافذ على الكمبيوتر المكتبي.
تتغيّر التنسيقات المتجاوبة/المتوافقة استنادًا إلى مساحة العرض المتاحة. تتراوح التغييرات بين تعديلات التخطيط الصغيرة التي تملأ المساحة (التصميم المتجاوب) إلى استبدال تخطيط بآخر تمامًا حتى يتمكّن تطبيقك من استيعاب أحجام الشاشة المختلفة على أفضل نحو (التصميم التكيُّفي).
بصفتها مجموعة أدوات تعريفية لواجهة المستخدم، فإنّ Jetpack Compose مثالية لتصميم تخطيطات و تنفيذها تتغيّر ديناميكيًا لعرض المحتوى بشكل مختلف على أحجام شاشات مختلفة.
إجراء تغييرات كبيرة على التنسيقات للعناصر القابلة للتجميع على مستوى المحتوى
تشغل العناصر القابلة للتجميع على مستوى التطبيق والمحتوى كل مساحة العرض المتاحة لتطبيقك. بالنسبة إلى هذه الأنواع من العناصر القابلة للتجميع، قد يكون من المنطقي تغيير التنسيق العام لتطبيقك على الشاشات الكبيرة.
تجنَّب استخدام قيم الأجهزة المادية لاتخاذ قرارات بشأن التنسيق. قد يكون من المغري اتخاذ قرارات استنادًا إلى قيمة ملموسة ثابتة (هل الجهاز هو جهاز لوحي؟ هل تتضمّن الشاشة الفعلية نسبة عرض إلى ارتفاع معيّنة؟)، ولكن قد لا تكون الإجابات عن هذه الأسئلة مفيدة لتحديد المساحة المتاحة لواجهة المستخدم.

على الأجهزة اللوحية، قد يكون التطبيق قيد التشغيل في وضع "نوافذ متعددة"، ما يعني أنّه قد يقسّم الشاشة مع تطبيق آخر. في وضع "نوافذ متعددة" على أجهزة الكمبيوتر المكتبي أو على نظام التشغيل ChromeOS، قد يكون التطبيق في نافذة يمكن تغيير حجمها. وقد يكون هناك أكثر من شاشة واحدة، مثل الجهاز القابل للطي. وفي كل هذه الحالات، لا تكون حجم الشاشة المادية ذات صلة بتحديد كيفية عرض المحتوى.
بدلاً من ذلك، يجب اتخاذ القرارات استنادًا إلى الجزء الفعلي من الشاشة المخصّص لتطبيقك والموضَّح من خلال مقاييس النافذة الحالية التي تقدّمها مكتبة WindowManager من Jetpack. للحصول على مثال على كيفية استخدام WindowManager في تطبيق Compose، يمكنك الاطّلاع على نموذج JetNews.
ويؤدي أيضًا جعل التنسيقات قابلة للتكيّف مع مساحة العرض المتاحة إلى تقليل مقدار المعالجة الخاصة المطلوبة لتتوافق مع الأنظمة الأساسية، مثل ChromeOS، وعوامل الشكل، مثل الأجهزة اللوحية والأجهزة القابلة للطي.
بعد تحديد مقاييس المساحة المتاحة لتطبيقك، يمكنك تحويل الحجم الأوّلي إلى فئة حجم نافذة كما هو موضّح في استخدام فئات حجم النافذة. فئات أحجام النوافذ هي نقاط توقّف مصمّمة لموازنة بساطة منطق التطبيق مع المرونة في تحسين تطبيقك لمعظم أحجام الشاشات. تشير فئات حجم النوافذ إلى النافذة العامة لتطبيقك، لذا استخدِم الفئات لقرارات التنسيق التي تؤثّر في تنسيق تطبيقك العام. يمكنك تمرير فئات حجم النافذة للأسفل كحالة، أو يمكنك تنفيذ منطق إضافي لإنشاء حالة مشتقة لتمريرها للأسفل إلى العناصر المُركّبة المتداخلة.
@Composable fun MyApp( windowSizeClass: WindowSizeClass = currentWindowAdaptiveInfo().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
يوفّر قيود measuring التي يمكنك استخدامها لاستدعاء عناصر قابلة للتجميع مختلفة استنادًا إلى مساحة العرض المتاحة. ومع ذلك، فإنّ هذا يأتي ببعض التكاليف، لأنّ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) } } } }
مزيد من المعلومات
لمزيد من المعلومات عن التنسيقات التكيُّفية في ميزة "الإنشاء"، اطّلِع على المراجع التالية:
أمثلة على التطبيقات
- CanonicalLayouts هو مستودع لأنماط التصميم التي أثبتت فعاليتها والتي توفّر تجربة مستخدم مثالية على الشاشات الكبيرة.
- يعرض تطبيق JetNews كيفية تصميم تطبيق يُعدّل واجهة المستخدم للاستفادة من مساحة العرض المتاحة.
- الردّ: هو نموذج قابل للتكيّف للتوافق مع الأجهزة الجوّالة والأجهزة اللوحية والأجهزة القابلة للطي
- الآن على Android هو تطبيق يستخدم تصاميم قابلة للتكيّف لتتوافق مع أحجام الشاشات المختلفة.
الفيديوهات