فئات حجم النوافذ هي مجموعة من نقاط التوقف لإطار العرض التي تستند إلى آراء تساعدك في تصميم التنسيقات سريعة الاستجابة/التكيفية وتطويرها واختبارها. توازن نقاط التوقف بين بساطة التنسيق ومرونة تحسين تطبيقك للحالات الفريدة.
تصنّف فئات أحجام النوافذ مساحة العرض المتاحة لتطبيقك على أنّها مكثّفة أو متوسطة أو موسّعة. يتم تصنيف العرض والارتفاع المتاحَين بشكل منفصل، لذا في أي وقت، يكون لتطبيقك فئتَان لحجم النافذة، إحداهما للعرض والأخرى للارتفاع. عادةً ما يكون العرض المتاح أكثر أهمية من الارتفاع المتاح بسبب انتشار الانتقال العمودي للأعلى أو للأسفل، لذا من المرجّح أن تكون فئة حجم نافذة العرض أكثر ملاءمةً لواجهة مستخدم تطبيقك.
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_width.png?authuser=4&hl=ar)
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_height.png?authuser=4&hl=ar)
كما هو موضّح في الصور، تتيح لك نقاط التوقف مواصلة التفكير في التنسيقات من حيث الأجهزة والإعدادات. يمثّل كل حدٍّ من حدود فئة الحجم حالة أغلبية سيناريوهات الأجهزة العادية، ما يمكن أن يكون مرجعًا مفعّلاً عند التفكير في تصميم التنسيقات استنادًا إلى حدود القطع.
فئة الحجم | نقطة الإيقاف | تمثيل الجهاز |
---|---|---|
العرض المكثّف | العرض < 600dp | %99.96 من الهواتف في الوضع العمودي |
عرض متوسط | 600dp ≤ العرض < 840dp | 93.73% من الأجهزة اللوحية في الوضع العمودي
أكبر شاشات داخلية مطوية في الوضع العمودي |
العرض الموسّع | العرض ≥ 840dp | 97.22% من الأجهزة اللوحية في الوضع الأفقي
أكبر شاشات داخلية مطوية أفقيًا |
الارتفاع المكثّف | الارتفاع < 480dp | 99.78% من الهواتف في الوضع الأفقي |
ارتفاع متوسط | 480dp ≤ الارتفاع < 900dp | 96.56% من الأجهزة اللوحية في الوضع الأفقي
%97.59 من الهواتف في الوضع العمودي |
الارتفاع الموسّع | الارتفاع ≥ 900dp | 94.25% من الأجهزة اللوحية في الوضع العمودي |
على الرغم من أنّه قد يكون من المفيد عرض فئات الحجم على أنّها أجهزة فعلية، لا يتم تحديد فئات حجم النوافذ بشكل صريح حسب حجم شاشة الجهاز. لا تكون فئات حجم النوافذ مخصّصة للمنطق من النوع isTablet. بدلاً من ذلك، يتم تحديد فئات حجم النوافذ حسب حجم النافذة المتاح لتطبيقك بغض النظر عن نوع الجهاز الذي يعمل عليه التطبيق، ما يؤدي إلى أثرين مهمَّين:
لا تضمن الأجهزة المادية فئة معيّنة لحجم النافذة. يمكن أن تختلف مساحة الشاشة المتاحة لتطبيقك عن حجم شاشة الجهاز لأسباب متعدّدة. على الأجهزة الجوّالة، يمكن أن يؤدي وضع "تقسيم الشاشة" إلى تقسيم الشاشة بين تطبيقَين. على نظام التشغيل ChromeOS، يمكن عرض تطبيقات Android في نوافذ من النوع المخصّص للكمبيوتر المكتبي والتي يمكن تغيير حجمها بشكل عشوائي. يمكن أن تتضمّن الأجهزة القابلة للطي شاشتَين مختلفتَين الحجم يمكن الوصول إليهما بشكلٍ منفصل من خلال طي الجهاز أو فتحه.
يمكن أن تتغيّر فئة حجم النافذة طوال مدة تشغيل تطبيقك. أثناء تشغيل تطبيقك، يمكن أن تؤدي تغييرات اتجاه الجهاز واستخدام التطبيقات المتعدّدة والطي/الفتح إلى تغيير مقدار المساحة المتوفّرة على الشاشة. نتيجةً لذلك، تكون فئة حجم النافذة ديناميكية، ويجب أن يتكيّف واجهة مستخدم تطبيقك تبعًا لذلك.
ترتبط فئات حجم النوافذ بنقاط التوقف المضغوطة والمتوسطة والموسّعة في إرشادات تنسيق Material Design. استخدِم فئات حجم النوافذ لاتخاذ قرارات عالية المستوى بشأن تنسيق التطبيق، مثل تحديد ما إذا كنت تريد استخدام تنسيق أساسي معيّن للاستفادة من مساحة الشاشة الإضافية.
يمكنك حساب القيمة الحالية
WindowSizeClass
باستخدام
WindowSizeClass#compute()
الدالة التي توفرها Jetpack
مكتبة WindowManager. المثال التالي
كيفية حساب فئة حجم النافذة وتلقّي التحديثات عند
تغييرات فئة حجم النافذة:
Kotlin
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) computeWindowSizeClasses() } }) computeWindowSizeClasses() } private fun computeWindowSizeClasses() { val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass // COMPACT, MEDIUM, or EXPANDED val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass // Use widthWindowSizeClass and heightWindowSizeClass. } }
Java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); computeWindowSizeClasses(); } }); computeWindowSizeClasses(); } private void computeWindowSizeClasses() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate() .computeCurrentWindowMetrics(this); int width = metrics.getBounds().width int height = metrics.getBounds().height() float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass() // COMPACT, MEDIUM, or EXPANDED WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass() // Use widthWindowSizeClass and heightWindowSizeClass. } }
فئات أحجام النوافذ الاختبارية
أثناء إجراء تغييرات على التنسيق، اختبِر سلوك التنسيق في جميع أحجام النوافذ، خاصةً عند عرض المحتوى في الوضع المكثّف والمتوسط والموسّع.
إذا كان لديك تنسيق حالي للشاشات المدمجة، عليك أولاً تحسين التنسيق لفئة حجم العرض الموسّع، لأنّ فئة الحجم هذه توفّر أكبر مساحة للمحتوى الإضافي وتغييرات واجهة المستخدم. بعد ذلك، حدِّد التنسيق المناسب لفئة الحجم المتوسط العرض، وفكِّر في إضافة تنسيق مخصّص.
الخطوات التالية
لمزيد من المعلومات عن كيفية استخدام فئات حجم النوافذ لإنشاء تصاميم متجاوبة/متكيّفة، اطّلِع على ما يلي:
بالنسبة إلى التنسيقات المستندة إلى ميزة "الإنشاء": إتاحة أحجام شاشات مختلفة
بالنسبة إلى التنسيقات المستندة إلى طريقة العرض: تصميم سريع الاستجابة/متوافق مع مختلف الأجهزة مع طرق العرض
للتعرّف على مزيد من المعلومات حول ما يجعل التطبيق رائعًا على جميع الأجهزة وأحجام الشاشات، اطّلِع على: