WindowInsets
هي واجهة برمجة التطبيقات العادية في Jetpack Compose للتعامل مع
مساحات الشاشة التي تحجبها واجهة مستخدم النظام جزئيًا أو كليًا. وتشمل هذه
المناطق شريط الحالة وشريط التنقّل ولوحة المفاتيح على الشاشة. يمكنك بدلاً من ذلك تمرير WindowInsetsRulers
محدَّد مسبقًا، مثل SafeDrawing
إلى Modifier.fitInside
أو Modifier.fitOutside
، لمحاذاة المحتوى مع أشرطة النظام وفتحة الشاشة أو إنشاء WindowInsetsRulers
مخصّص.
مزايا WindowInsetsRulers
- تجنُّب تعقيد الاستهلاك: تعمل هذه الميزة خلال مرحلة تحديد موضع الإعلان في التصميم. وهذا يعني أنّه يتجاوز تمامًا سلسلة الاستهلاك المضمّنة ويمكنه دائمًا توفير المواضع الصحيحة والمطلقة لأشرطة النظام وفتحات الشاشة، بغض النظر عن ما فعلته تنسيقات العناصر الرئيسية. يساعد استخدام الطريقتَين
Modifier.fitInside
أوModifier.fitOutside
في حلّ المشاكل عندما تستهلك عناصر Composables الأصلية الحواف الداخلية بشكل غير صحيح. - تجنُّب أشرطة النظام بسهولة: تساعد هذه الطريقة محتوى تطبيقك في تجنُّب أشرطة النظام وفتحة الشاشة، ويمكن أن تكون أكثر وضوحًا من استخدام
WindowInsets
مباشرةً. - قابلة للتخصيص بشكل كبير: يمكن للمطوّرين محاذاة المحتوى مع مساطر مخصّصة، والتحكّم بدقة في التنسيقات باستخدام التنسيقات المخصّصة.
عيوب WindowInsetsRulers
- لا يمكن استخدامها في القياس: بما أنّها تعمل أثناء مرحلة تحديد الموضع، فإنّ معلومات الموضع التي تقدّمها غير متاحة أثناء مرحلة القياس السابقة.
مواءمة المحتوى مع طرق Modifier
تسمح السمة 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) } } } }
يعرض الفيديو التالي مثالاً على استهلاك غير صحيح لمساحة IME الداخلية
بسبب عنصر رئيسي في أعلى التسلسل الهرمي في الصورة على اليمين، واستخدام مساطر مخصّصة
لحلّ المشكلة في الصورة على اليسار. يظهر الحشو الإضافي أسفل TextField
Composable لأنّ الحاوية الرئيسية لم تستخدم حشو شريط التنقل. يتم وضع الطفل في الموقع الصحيح في الصورة اليمنى باستخدام مسطرة مخصّصة، كما هو موضّح في نموذج الرمز البرمجي السابق.
التأكّد من أنّ الوالدَين لديهما قيود
لاستخدام WindowInsetsRulers
بأمان، تأكَّد من أنّ الوالد يقدّم قيودًا صالحة. يجب أن يكون للعناصر الرئيسية حجم محدّد، ولا يمكن أن تعتمد على حجم عنصر فرعي يستخدم WindowInsetsRulers
. استخدِم fillMaxSize
أو أدوات تعديل الحجم الأخرى
في عناصر Composables الرئيسية.
وبالمثل، قد يؤدي وضع عنصر قابل للإنشاء يستخدم WindowInsetsRulers
داخل حاوية قابلة للتمرير مثل verticalScroll
إلى حدوث سلوك غير متوقّع لأنّ الحاوية القابلة للتمرير توفّر قيودًا غير محدودة على الارتفاع، وهي غير متوافقة مع منطق المسطرة.