فئات حجم النافذة

فئات حجم النافذة هي مجموعة من نقاط التوقف بإطار العرض التي تساعدك على تصميم وتطوير واختبار التخطيطات سريعة الاستجابة/التكيفية. رصيد نقاط الإيقاف بساطة التخطيط مع المرونة في تحسين تطبيقك للحالات الفريدة.

تصنِّف فئات حجم النافذة مساحة العرض المتاحة لتطبيقك على أنّها مكثف أو متوسط أو موسَّع. تم تصنيف العرض والارتفاع المتاحَين. منفصل، لذا في أي وقت، يشتمل تطبيقك على نافذتين الفئات - فئة للعرض وفئة للارتفاع. عادةً ما يكون العرض المتاح أكبر أكثر أهمية من الارتفاع المتاح نظرًا للانتشار الرأسي للتمرير العمودي، تكون فئة حجم نافذة العرض أكثر صلة بواجهة مستخدم تطبيقك.

الشكل 1. تمثيلات لفئات حجم النافذة المستندة إلى العرض.
الشكل 2. تمثيلات لفئات حجم النافذة المستندة إلى الارتفاع.

كما هو موضح في الأشكال، تسمح لك نقاط التوقف بمواصلة التفكير حول التخطيطات من حيث الأجهزة والتهيئات. كل نقطة فاصلة لفئة الحجم يمثل حالة الأغلبية لسيناريوهات الأجهزة النموذجية، والتي قد تكون مفيدة إطار مرجعي عندما تفكر في تصميم النموذج المستند إلى نقطة التوقف وتخطيطات.

فئة المقاس نقطة الإيقاف تمثيل الجهاز
عرض مضغوط العرض < 600 بكسل مستقل الكثافة 99.96% من الهواتف في الوضع العمودي
عرض متوسط 600dp ≤ العرض < 840 بكسل مستقل الكثافة 93.73٪ من الأجهزة اللوحية في الوضع العمودي،

معظم الشاشات الداخلية الكبيرة غير المطوية في الوضع العمودي

عرض موسّع العرض ≥ 840 بكسل مستقل الكثافة 97.22٪ من الأجهزة اللوحية باتجاه أفقي،

معظم الشاشات الداخلية الكبيرة غير المطوية في الوضع الأفقي

ارتفاع مضغوط الارتفاع < 480 بكسل مستقل الكثافة 99.78% من الهواتف في الوضع الأفقي
متوسط الارتفاع 480dp ≤ الارتفاع < 900 بكسل مستقل الكثافة 96.56٪ من الأجهزة اللوحية باتجاه أفقي،

97.59% من الهواتف في الوضع العمودي

ارتفاع موسَّع الارتفاع ≥ 900 بكسل مستقل الكثافة 94.25% من الأجهزة اللوحية في الوضع العمودي

على الرغم من أن تصور فئات الحجم كأجهزة مادية قد يكون مفيدًا، إلا أن حجم النافذة لا يتم تحديد الفئات صراحةً من خلال حجم شاشة الجهاز. نافذة وفئات الحجم غير مخصصة لمنطق isTablet. بدلاً من ذلك، يتم تحديد فئات الحجم حسب حجم النافذة المتاحة لتطبيقك. بغض النظر عن نوع الجهاز الذي يعمل عليه التطبيق، وهو نوعان مهمان الآثار المترتبة على ذلك:

  • لا تضمن الأجهزة المادية فئة محدَّدة لحجم النافذة. تشير رسالة الأشكال البيانية يمكن أن تختلف مساحة الشاشة المتاحة لتطبيقك عن حجم شاشة الجهاز لعدة أسباب. يمكن أن يتيح وضع تقسيم الشاشة على الأجهزة الجوّالة لتقسيم الشاشة بين تطبيقين. على نظام التشغيل ChromeOS، يمكن لتطبيقات Android إجراء ما يلي: ستظهر في نوافذ حرة يمكن تغيير حجمها عشوائيًا. يمكن أن تحتوي الهواتف القابلة للطي على شاشتَين مختلفتَين الحجم يمكن الوصول إليها بشكلٍ فردي. عن طريق طي الجهاز أو فتحه.

  • يمكن أن تتغيّر فئة حجم النافذة طوال عمر تطبيقك. أثناء تشغيل تطبيقك، يتغيّر اتجاه الجهاز وتنفيذ مهام متعددة يمكن أن يؤدي الطي/الفتح إلى تغيير مقدار مساحة الشاشة المتاحة. نتيجة لذلك، أُنشئت مكتبة مات بلوت ليب في ونتيجة لذلك، تكون فئة حجم النافذة ديناميكية، وينبغي أن تتكيف واجهة مستخدم التطبيق وفقًا لذلك.

ترتبط فئات حجم النوافذ بنقاط التوقف الصغيرة والمتوسطة والمتوسعة في تخطيط Material Design من Google. استخدم فئات حجم النافذة لاتخاذ قرارات عالية المستوى بشأن تخطيط التطبيقات، مثل تحديد ما إذا كان ينبغي استخدام تخطيط أساسي معين للاستفادة من مساحة شاشة إضافية.

يمكنك حساب القيمة الحالية 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.
    }
}

اختبار فئات حجم النافذة

أثناء إجراء تغييرات على التخطيط، اختبر سلوك التخطيط عبر جميع أحجام النوافذ، خاصةً في عرض نقاط التوقف الصغيرة والمتوسطة والموسعة.

إذا كان لديك تخطيط حالي للشاشات المكثّفة، فاحرص أولاً على تحسين التخطيط لفئة حجم العرض الموسَّع، حيث توفّر فئة الحجم هذه أكبر مساحة للحصول على مزيد من التغييرات في المحتوى وواجهة المستخدم. ثم حدد التخطيط المنطقي فئة الحجم المتوسط العرض؛ ففكر في إضافة تخطيط متخصص.

الخطوات التالية

اطّلِع على مزيد من المعلومات حول كيفية استخدام فئات حجم النافذة لإنشاء محتوى متجاوب أو تكيُّفي. التخطيطات، فراجع ما يلي:

للتعرّف على مزيد من المعلومات حول العوامل التي تجعل التطبيق رائعًا على جميع الأجهزة وأحجام الشاشات، راجِع: