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

بعد أن يتحكّم النشاط في معالجة جميع عمليات الإدراج، يمكنك استخدام واجهات برمجة التطبيقات في 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() أي مساحة متروكة. وبالتالي، لا يتم استخدام أي هوامش داخلية، ويتطابق ارتفاع Spacer مع أشرطة النظام السفلية.

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

عند إغلاق محرر أسلوب الإدخال، تحدث التغييرات بشكل عكسي: يتوسّع 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.

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