إعداد مساحات النافذة

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

التعامل مع عمليات الإدراج باستخدام الحشو أو عناصر تعديل الحجم

على سبيل المثال، هذه هي الطريقة الأساسية لتطبيق الهوامش الداخلية على محتوى تطبيقك بالكامل:

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    enableEdgeToEdge()

    setContent {
        Box(Modifier.safeDrawingPadding()) {
            // the rest of the app
        }
    }
}

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

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

هناك ثلاث طرق للتعامل مع الحواف الداخلية لتعديل تصميمات Composable:

معدِّلات المساحة المتروكة

تطبِّق Modifier.windowInsetsPadding(windowInsets: WindowInsets) مساحات إزاحة النافذة المحدّدة كمسافة بادئة، وتعمل تمامًا مثل Modifier.padding. على سبيل المثال، تطبّق Modifier.windowInsetsPadding(WindowInsets.safeDrawing) هوامش الإدخال الآمنة للرسم كمسافة بادئة على جميع الجوانب الأربعة.

تتوفّر أيضًا عدّة طرق مساعدة مدمَجة لأنواع الحواف الداخلية الأكثر شيوعًا. Modifier.safeDrawingPadding() هي إحدى هذه الطرق، وهي تعادل Modifier.windowInsetsPadding(WindowInsets.safeDrawing). تتوفّر معدّلات مشابهة لأنواع الإضافات الأخرى.

معدِّلات حجم الإدراج

تطبِّق المعدِّلات التالية مقدارًا من هوامش النافذة الداخلية من خلال ضبط حجم المكوّن ليكون بحجم الهوامش الداخلية:

Modifier.windowInsetsStartWidth(windowInsets: WindowInsets)

تطبيق الجانب الأيمن من windowInsets كعرض (مثل Modifier.width)

Modifier.windowInsetsEndWidth(windowInsets: WindowInsets)

تطبيق الجانب الأخير من windowInsets كعرض (مثل Modifier.width)

Modifier.windowInsetsTopHeight(windowInsets: WindowInsets)

تطبيق الجانب العلوي من windowInsets كارتفاع (مثل Modifier.height)

Modifier.windowInsetsBottomHeight(windowInsets: WindowInsets)

تطبيق الجانب السفلي من windowInsets كارتفاع (مثل Modifier.height)

تكون معدِّلات الحجم هذه مفيدة بشكل خاص لتحديد حجم Spacer يشغل مساحة الحواف الداخلية:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

استهلاك المساحة الداخلية

تستهلك أدوات تعديل المساحة المتروكة الداخلية (windowInsetsPadding وأدوات المساعدة مثل safeDrawingPadding) تلقائيًا جزءًا من المساحات المتروكة الداخلية التي يتم تطبيقها كمساحة متروكة. أثناء التوغّل أكثر في شجرة التركيب، تعرف أدوات تعديل المساحة المتروكة الداخلية المتداخلة وأدوات تعديل حجم المساحة المتروكة الداخلية أنّ بعض أجزاء المساحات المتروكة الداخلية قد استهلكتها أدوات تعديل المساحة المتروكة الداخلية الخارجية، وتتجنّب استخدام الجزء نفسه من المساحات المتروكة الداخلية أكثر من مرة، ما قد يؤدي إلى توفير مساحة إضافية كبيرة جدًا.

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

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

بالنظر إلى مثال LazyColumn نفسه كما كان من قبل، يتم تغيير حجم LazyColumn باستخدام المعدِّل imePadding. داخل LazyColumn، يتم ضبط حجم العنصر الأخير ليكون بارتفاع أسفل أشرطة النظام:

LazyColumn(
    Modifier.imePadding()
) {
    // Other content
    item {
        Spacer(
            Modifier.windowInsetsBottomHeight(
                WindowInsets.systemBars
            )
        )
    }
}

عند إغلاق محرر أسلوب الإدخال، لا يضيف المعدِّل imePadding() أي مساحة متروكة لأنّ محرر أسلوب الإدخال ليس له ارتفاع. بما أنّ المعدِّل imePadding() لا يطبّق أي مساحة متروكة، لا يتم استخدام أي مساحات داخلية، وسيكون ارتفاع Spacer هو حجم الجانب السفلي من أشرطة النظام.

عند فتح محرّك أساليب الإدخال، يتم تحريك هوامش IME الداخلية لتتطابق مع حجم محرّك أساليب الإدخال، ويبدأ المعدِّل imePadding() في تطبيق الحشو السفلي لتغيير حجم LazyColumn عند فتح محرّك أساليب الإدخال. عندما يبدأ المعدِّل imePadding() في تطبيق مساحة الحشو السفلية، يبدأ أيضًا في استهلاك مقدار المساحات الداخلية هذا. لذلك، يبدأ ارتفاع Spacer في الانخفاض، لأنّ جزءًا من المساحة المخصّصة لأشرطة النظام قد تم تطبيقه من خلال المعدِّل imePadding(). عندما يطبّق المعدِّل imePadding() مقدارًا من المساحة المتروكة في أسفل الشاشة أكبر من أشرطة النظام، يصبح ارتفاع Spacer صفرًا.

عند إغلاق أداة IME، تحدث التغييرات بالعكس: يبدأ Spacer في التوسّع من ارتفاع صفر عندما يطبّق imePadding() قيمة أقل من الجانب السفلي لأشرطة النظام، إلى أن يتطابق Spacer أخيرًا مع ارتفاع الجانب السفلي لأشرطة النظام عند إكمال إخفاء أداة IME.

الشكل 2. عمود كسول من الحافة إلى الحافة مع TextField.
.

يتم تحقيق هذا السلوك من خلال التواصل بين جميع معدِّلات windowInsetsPadding، ويمكن التأثير فيه بطريقتين أخريين.

تستهلك السمة Modifier.consumeWindowInsets(insets: WindowInsets) أيضًا الحواف الداخلية بالطريقة نفسها التي تستهلك بها السمة Modifier.windowInsetsPadding، ولكنها لا تطبّق الحواف الداخلية المستهلكة كحاشية. يكون ذلك مفيدًا عند استخدامه مع معدِّلات حجم الحواف الداخلية، للإشارة إلى العناصر الفرعية بأنّه تم استهلاك مقدار معيّن من الحواف الداخلية:

Column(Modifier.verticalScroll(rememberScrollState())) {
    Spacer(Modifier.windowInsetsTopHeight(WindowInsets.systemBars))

    Column(
        Modifier.consumeWindowInsets(
            WindowInsets.systemBars.only(WindowInsetsSides.Vertical)
        )
    ) {
        // content
        Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
    }

    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.systemBars))
}

يتشابه سلوك Modifier.consumeWindowInsets(paddingValues: PaddingValues) إلى حد كبير مع سلوك الإصدار الذي يتضمّن وسيطة WindowInsets، ولكنّه يستخدِم PaddingValues عشوائيًا. يكون ذلك مفيدًا لإعلام الأطفال عندما يتم توفير مساحة متروكة أو تباعد من خلال آلية أخرى غير معدّلات المساحة المتروكة الداخلية، مثل Modifier.padding عادي أو فواصل بارتفاع ثابت:

Column(Modifier.padding(16.dp).consumeWindowInsets(PaddingValues(16.dp))) {
    // content
    Spacer(Modifier.windowInsetsBottomHeight(WindowInsets.ime))
}

في الحالات التي تكون فيها حواف النافذة الأولية مطلوبة بدون استهلاك، استخدِم قيم WindowInsets مباشرةً أو استخدِم WindowInsets.asPaddingValues() لعرض PaddingValues للحواف التي لم تتأثر بالاستهلاك. ومع ذلك، بسبب التحذيرات التالية، من الأفضل استخدام أدوات تعديل المساحة المتروكة الداخلية للنافذة وأدوات تعديل حجم المساحة المتروكة الداخلية للنافذة حيثما أمكن ذلك.

فواصل الهوامش ومراحل Jetpack Compose

تستخدم Compose واجهات برمجة التطبيقات الأساسية في AndroidX لتعديل الحواف الداخلية وإنشاء رسوم متحركة لها، وتستخدم هذه الواجهات واجهات برمجة التطبيقات الأساسية في النظام الأساسي التي تدير الحواف الداخلية. وبسبب سلوك هذه المنصة، ترتبط الحواف الداخلية بعلاقة خاصة مع مراحل Jetpack Compose.

يتم تعديل قيمة الهوامش الداخلية بعد مرحلة التركيب، ولكن قبل مرحلة التنسيق. وهذا يعني أنّ قراءة قيمة الحواف الداخلية في التكوين تستخدم بشكل عام قيمة الحواف الداخلية التي تتأخر بمقدار إطار واحد. تم تصميم المعدِّلات المضمّنة الموضّحة في هذه الصفحة لتأخير استخدام قيم الهوامش الداخلية إلى حين اكتمال مرحلة التنسيق، ما يضمن استخدام قيم الهوامش الداخلية في الإطار نفسه الذي يتم تعديلها فيه.