WindowInsets هي واجهة برمجة التطبيقات العادية في Jetpack Compose للتعامل مع
مساحات الشاشة التي تحجبها واجهة مستخدم النظام جزئيًا أو كليًا. وتشمل هذه المساحات شريط الحالة وشريط التنقّل ولوحة المفاتيح على الشاشة. يمكنك
بدلاً من ذلك تمرير WindowInsetsRulers محدّدة مسبقًا، مثل
SafeDrawing إلى Modifier.fitInside أو Modifier.fitOutside
لمحاذاة المحتوى مع أشرطة النظام وصورة مقطوعة للشاشة أو إنشاء
WindowInsetsRulers مخصّصة.
مزايا WindowInsetsRulers
- تجنُّب تعقيد الاستهلاك: تعمل هذه الميزة خلال مرحلة الموضع
من التنسيق. وهذا يعني أنّها تتجاوز تمامًا سلسلة استهلاك المساحات الداخلية ويمكنها دائمًا توفير المواضع المطلقة الصحيحة لأشرطة النظام وقطع الشاشة، بغض النظر عن الإجراءات التي اتّخذتها تنسيقات العناصر الرئيسية. يساعد استخدام الطريقتَين
Modifier.fitInsideأوModifier.fitOutsideفي حلّ المشاكل عندما تستهلك العناصر المركّبة السلفية المساحات الداخلية بشكل غير صحيح. - تجنُّب أشرطة النظام بسهولة: تساعد هذه الميزة محتوى تطبيقك في تجنُّب أشرطة النظام وصورة مقطوعة للشاشة، ويمكن أن تكون أكثر وضوحًا من استخدام
WindowInsetsمباشرةً. - قابلة للتخصيص بدرجة كبيرة: يمكن للمطوّرين محاذاة المحتوى مع المسطرة المخصّصة، و التحكّم بدقة في تنسيقاتهم باستخدام التنسيقات المخصّصة.
عيوب WindowInsetsRulers
- لا يمكن استخدامها للقياس: بما أنّها تعمل خلال مرحلة الموضع ، فإنّ معلومات الموضع التي تقدّمها غير متاحة خلال مرحلة القياس السابقة.
محاذاة المحتوى باستخدام طرق المعدِّل
Modifier.fitInside يسمح للتطبيقات بمحاذاة المحتوى مع أشرطة النظام و
قطع الشاشة. ويمكن استخدامه بدلاً من WindowInsets.
Modifier.fitOutside عادةً ما يكون هو معكوس Modifier.fitInside.
على سبيل المثال، للتحقّق من أنّ محتوى التطبيق يتجنّب أشرطة النظام وقطع الشاشة، يمكنك استخدام fitInside(WindowInsetsRulers.safeDrawing.current).
@Composable fun FitInsideDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() // Or DisplayCutout, Ime, NavigationBars, StatusBar, etc... .fitInside(WindowInsetsRulers.SafeDrawing.current) ) }
يوضّح الجدول التالي كيف سيبدو محتوى تطبيقك باستخدام المسطرة المحدّدة مسبقًا مع Modifier.fitInside أو Modifier.fitOutside.
| نوع المسطرة المحدّدة مسبقًا | ||
|---|---|---|
![]() |
![]() |
|
![]() |
لا ينطبق |
|
![]() |
![]() |
|
![]() |
لا ينطبق (استخدِم |
|
![]() |
![]() |
يتطلّب استخدام Modifier.fitInside وModifier.fitOutside أن تكون العناصر المركّبة مقيّدة. وهذا يعني أنّه عليك تحديد معدِّلات، مثل Modifier.size أو Modifier.fillMaxSize.
تعرض بعض المسطرة، مثل Modifier.fitOutside على SafeDrawing وSystemBars، مسطرة متعددة. في هذه الحالة، يضع Android العنصر المركّب باستخدام مسطرة واحدة من اليسار أو الأعلى أو اليمين أو الأسفل.
تجنُّب أداة IME باستخدام Modifier.fitInside
للتعامل مع العناصر السفلية باستخدام أداة IME مع Modifier.fitInside، مرِّر RectRuler تأخذ القيمة الداخلية لـ NavigationBar وIme.
@Composable fun FitInsideWithImeDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.NavigationBars.current, WindowInsetsRulers.Ime.current ) ) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier.align(Alignment.BottomStart).fillMaxWidth() ) } }
تجنُّب شريط الحالة وشريط العنوان باستخدام Modifier.fitInside
وبالمثل، للتحقّق من أنّ العناصر العلوية تتجنّب شريط الحالة وشريط العنوان معًا باستخدام Modifier.fitInsider، مرِّر RectRuler تأخذ القيمة الداخلية لـ StatusBars وCaptionBar.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
إنشاء WindowInsetsRulers مخصّصة
يمكنك محاذاة المحتوى مع المسطرة المخصّصة. على سبيل المثال، لنفترض حالة استخدام يتعامل فيها عنصر مركّب رئيسي بشكل غير صحيح مع المساحات الداخلية، ما يؤدي إلى حدوث مشاكل في المساحة المتروكة في عنصر ثانوي لاحق. على الرغم من أنّه يمكن حلّ هذه المشكلة بطرق أخرى، بما في ذلك باستخدام Modifier.fitInside، يمكنك أيضًا إنشاء مسطرة مخصّصة لمحاذاة العنصر المركّب الثانوي بدقة بدون الحاجة إلى حلّ المشكلة في العنصر الرئيسي السابق، كما هو موضّح في المثال والفيديو التاليَين:
@Composable fun WindowInsetsRulersDemo(modifier: Modifier) { Box( contentAlignment = BottomCenter, modifier = modifier .fillMaxSize() // The mistake that causes issues downstream, as .padding doesn't consume insets. // While it's correct to instead use .windowInsetsPadding(WindowInsets.navigationBars), // assume it's difficult to identify this issue to see how WindowInsetsRulers can help. .padding(WindowInsets.navigationBars.asPaddingValues()) ) { TextField( value = "Demo IME Insets", onValueChange = {}, modifier = modifier // Use alignToSafeDrawing() instead of .imePadding() to precisely place this child // Composable without having to fix the parent upstream. .alignToSafeDrawing() // .imePadding() // .fillMaxWidth() ) } } fun Modifier.alignToSafeDrawing(): Modifier { return layout { measurable, constraints -> if (constraints.hasBoundedWidth && constraints.hasBoundedHeight) { val placeable = measurable.measure(constraints) val width = placeable.width val height = placeable.height layout(width, height) { val bottom = WindowInsetsRulers.SafeDrawing.current.bottom .current(0f).roundToInt() - height val right = WindowInsetsRulers.SafeDrawing.current.right .current(0f).roundToInt() val left = WindowInsetsRulers.SafeDrawing.current.left .current(0f).roundToInt() measurable.measure(Constraints.fixed(right - left, height)) .place(left, bottom) } } else { val placeable = measurable.measure(constraints) layout(placeable.width, placeable.height) { placeable.place(0, 0) } } } }
يعرض الفيديو التالي مثالاً على استهلاك المساحات الداخلية للوحة المفاتيح على الشاشة بشكل غير صحيح بسبب عنصر رئيسي سابق في الصورة على اليمين، واستخدام المسطرة المخصّصة لحلّ المشكلة على اليسار. تظهر مساحة متروكة إضافية أسفل العنصر المركّب TextField لأنّ العنصر الرئيسي لم يستهلك المساحة المتروكة لشريط التنقّل. يتم وضع العنصر الثانوي في الموضع الصحيح في الصورة على اليسار باستخدام مسطرة مخصّصة كما هو موضّح في عينة التعليمات البرمجية السابقة.
التأكّد من أنّ العناصر الرئيسية مُقيَّدة
لاستخدام WindowInsetsRulers بأمان، تأكَّد من أنّ العنصر الرئيسي يوفّر قيودًا صالحة. يجب أن يكون للعناصر الرئيسية حجم محدّد ولا يمكن أن تعتمد على حجم عنصر ثانوي يستخدم WindowInsetsRulers. استخدِم fillMaxSize أو معدِّلات الحجم الأخرى على العناصر المركّبة الرئيسية.
وبالمثل، يمكن أن يؤدي وضع دالة مركّبة تستخدم WindowInsetsRulers داخل حاوية قابلة للتمرير، مثل verticalScroll، إلى حدوث سلوك غير متوقّع لأنّ الحاوية القابلة للتمرير توفّر قيودًا غير محدودة للارتفاع، وهي غير متوافقة مع منطق المسطرة.







