WindowInsets הוא ה-API הרגיל ב-Jetpack Compose לטיפול באזורים במסך שמוסתרים באופן חלקי או מלא על ידי ממשק המשתמש של המערכת. האזורים האלה כוללים את שורת הסטטוס, סרגל הניווט והמקלדת הווירטואלית. אפשר גם להעביר WindowInsetsRulers מוגדרים מראש כמו SafeDrawing אל Modifier.fitInside או Modifier.fitOutside כדי להתאים את התוכן לסרגלי המידע ולמגרעת במסך, או ליצור WindowInsetsRulers בהתאמה אישית.
היתרונות של WindowInsetsRulers
- מונע מורכבות בצריכה: הוא פועל במהלך שלב המיקום של הפריסה. זה אומר שהיא עוקפת לחלוטין את שרשרת צריכת ה-inset, ותמיד יכולה לספק את המיקומים המוחלטים הנכונים של סרגלי המידע והמגרעות במסך, בלי קשר לפעולות שבוצעו בפריסות האם. השיטות
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.fitInside, מעבירים RectRuler שמקבל את הערך הפנימי ביותר של StatusBars ו-CaptionBar.
@Composable fun FitInsideWithStatusAndCaptionBarDemo(modifier: Modifier) { Box( modifier = modifier .fillMaxSize() .fitInside( RectRulers.innermostOf( WindowInsetsRulers.StatusBars.current, WindowInsetsRulers.CaptionBar.current ) ) ) }
יצירת WindowInsetsRulers בהתאמה אישית
אתם יכולים ליישר את התוכן לפי סרגלים בהתאמה אישית. לדוגמה, נניח שיש תוכן קומפוזבילי הורה שמטפל בצורה לא נכונה ב-inset, וכתוצאה מכך יש בעיות עם המרווח הפנימי בתוכן קומפוזבילי צאצא. אפשר לפתור את הבעיה הזו בדרכים אחרות, כולל שימוש ב-Modifier.fitInside, אבל אפשר גם ליצור סרגל בהתאמה אישית כדי ליישר במדויק את ה-composable הצאצא בלי לתקן את הבעיה ב-composable ההורה, כמו שמוצג בדוגמה ובסרטון הבאים:
@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) } } } }
בסרטון הבא מוצגת דוגמה לבעיה בשימוש ב-inset של IME שנגרמה על ידי רכיב הורה קודם בתמונה שמשמאל, ושימוש בסרגלים מותאמים אישית כדי לפתור את הבעיה בתמונה שמימין. ריפוד נוסף מוצג מתחת ל-TextField
Composable כי הריפוד של סרגל הניווט לא נצרך על ידי ההורה. הילד ממוקם במיקום הנכון בתמונה השמאלית באמצעות סרגל מותאם אישית, כפי שמוצג בדוגמת הקוד הקודמת.
אימות שההורים מוגבלים
כדי להשתמש ב-WindowInsetsRulers באופן בטוח, צריך לוודא שההורה מספק אילוצים תקינים. לרכיבי הורה צריך להיות גודל מוגדר, והם לא יכולים להיות תלויים בגודל של רכיב צאצא שמשתמש במאפיין WindowInsetsRulers. משתמשים ב-fillMaxSize או בשינויי גודל אחרים ברכיבי Composable הורה.
באופן דומה, הצבת רכיב Composable שמשתמש ב-WindowInsetsRulers בתוך מאגר שניתן לגלילה כמו verticalScroll עלולה לגרום להתנהגות בלתי צפויה, כי המאגר שניתן לגלילה מספק אילוצי גובה בלתי מוגבלים, שלא תואמים ללוגיקה של הסרגל.







