אחרי שה-Activity שולט בטיפול בכל ה-insets, אתם יכולים להשתמש בממשקי API של Compose כדי לוודא שהתוכן לא מוסתר ושהרכיבים שאפשר לקיים איתם אינטראקציה לא חופפים לממשק המשתמש של המערכת. ממשקי ה-API האלה גם מסנכרנים את פריסת האפליקציה עם שינויים ב-inset.
טיפול בתוספות באמצעות שינוי המרווח הפנימי או הגודל
לדוגמה, זו השיטה הבסיסית ביותר להחלת השוליים על התוכן של האפליקציה כולה:
override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) enableEdgeToEdge() setContent { Box(Modifier.safeDrawingPadding()) { // the rest of the app } } }
קטע הקוד הזה מחיל את ה-insets של החלון safeDrawing כמרווח פנימי מסביב לכל התוכן של האפליקציה. זה מבטיח שרכיבים שאפשר לקיים איתם אינטראקציה לא יחפפו לממשק המשתמש של המערכת, אבל זה גם אומר שאף חלק מהאפליקציה לא יצויר מאחורי ממשק המשתמש של המערכת כדי ליצור אפקט מקצה לקצה. כדי לנצל את כל החלון, צריך לכוונן את המיקום שבו מוסיפים את השוליים בכל מסך או בכל רכיב.
כל סוגי ה-inset האלה מונפשים באופן אוטומטי באמצעות אנימציות IME שהוסבו לגרסאות קודמות של API 21. כתוצאה מכך, כל הפריסות שמשתמשות ב-inset האלה גם מונפשות באופן אוטומטי כשהערכים של ה-inset משתנים.
יש שלוש דרכים לטפל ב-inset כדי להתאים את הפריסות של Composable:
ערכים לשינוי המרווח הפנימי
Modifier.windowInsetsPadding(windowInsets: WindowInsets) מחיל את ה-window insets הנתונים כמרווח פנימי, בדיוק כמו Modifier.padding.
לדוגמה, Modifier.windowInsetsPadding(WindowInsets.safeDrawing) מחיל את השוליים הפנימיים של האזור הבטוח לציור כריפוד בכל 4 הצדדים.
יש גם כמה שיטות מובנות לסוגי ה-inset הנפוצים ביותר.
Modifier.safeDrawingPadding() היא שיטה אחת כזו, ששווה ל-Modifier.windowInsetsPadding(WindowInsets.safeDrawing). בטבלה הבאה מפורטים משתני ה-padding המובנים וסוג ה-WindowInsets שכל אחד מהם מחיל:
כדי לדעת מה כל סוג של הוספה כולל, קראו את המאמר מידע על הוספות לחלונות.
משנים את גודל התמונה המוקטנת
המשתנים הבאים מחילים כמות של הוספות לחלון על ידי הגדרת גודל הרכיב לגודל של ההוספות:
החלת הצד ההתחלתי של windowInsets כרוחב (כמו |
|
החלת הצד הסופי של windowInsets כרוחב (כמו |
|
החלת הצד העליון של windowInsets בתור הגובה (כמו |
|
|
החלת הצד התחתון של windowInsets כגובה (כמו |
המשתנים האלה שימושיים במיוחד לקביעת הגודל של Spacer שתופס את המרחב של ה-inset:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
צריכת תשלומים
המשתנים של ריפוד ה-inset (windowInsetsPadding ורכיבי עזר כמו safeDrawingPadding) צורכים באופן אוטומטי את החלק של ה-inset שמוחל כריפוד. כשמעמיקים בעץ הקומפוזיציה, משתני ה-padding של ה-inset המקוננים ומשתני הגודל של ה-inset יודעים שחלק מה-insets כבר נוצלו על ידי משתני ה-padding של ה-inset החיצוניים, ונמנעים משימוש באותו חלק של ה-insets יותר מפעם אחת, מה שעלול לגרום ליותר מדי שטח נוסף.
משני הגודל של ה-inset גם מונעים שימוש באותו חלק של ה-inset יותר מפעם אחת אם כבר נעשה שימוש ב-inset. עם זאת, מכיוון שהם משנים את הגודל שלהם באופן ישיר, הם לא צורכים את ה-inset בעצמם.
כתוצאה מכך, שינוי של משתני ה-padding המקוננים משנה באופן אוטומטי את כמות ה-padding שמוחלת על כל רכיב Composable.
אם נסתכל על אותה דוגמה של LazyColumn כמו קודם, הגודל של LazyColumn משתנה על ידי המשנה imePadding. בתוך LazyColumn, הפריט האחרון מוגדר בגובה של החלק התחתון של סרגלי המידע:
LazyColumn( Modifier.imePadding() ) { // Other content item { Spacer( Modifier.windowInsetsBottomHeight( WindowInsets.systemBars ) ) } }
כשה-IME סגור, imePadding() לא מוסיף ריפוד. כתוצאה מכך, לא נעשה שימוש ב-inset, והגובה של Spacer תואם לסרגלי המידע התחתונים.
כשה-IME נפתח, ה-inset של ה-IME מונפש בהתאם לגודל של ה-IME, והמשתנה imePadding() מתחיל להחיל מרווח פנימי תחתון כדי לשנות את הגודל של LazyColumn כשה-IME נפתח. כשהמשתנה imePadding() מתחיל להחיל את המרווח הפנימי התחתון, הוא גם מתחיל לצרוך את הכמות הזו של ה-insets. לכן, הגובה של Spacer מתחיל לרדת, כי חלק מהריווח של סרגלי המידע כבר הוחל על ידי המשנה imePadding(). אחרי שהמשתנה imePadding() מוסיף ריפוד תחתון שגדול יותר מסרגלי המידע, הגובה של Spacer הוא אפס.
כשה-IME נסגר, השינויים מתרחשים בסדר הפוך: Spacer מתרחב מגובה אפס, כי imePadding() מחיל פחות מסרגלי המידע התחתונים.
לבסוף, הגובה של Spacer תואם לסרגלי המידע אחרי שהאנימציה של ה-IME מסתיימת.
TextField.ההתנהגות הזו מתבצעת באמצעות תקשורת בין כל המשנים של windowInsetsPadding, ויכולה להיות מושפעת בכמה דרכים אחרות.
Modifier.consumeWindowInsets(insets: WindowInsets) גם צורך את ה-insets באותו אופן כמו Modifier.windowInsetsPadding, אבל הוא לא מחיל את ה-insets שנצרכו כ-padding. האפשרות הזו שימושית בשילוב עם מקשי הצירוף של גודל ה-inset, כדי לציין לאלמנטים אחים שכמות מסוימת של inset כבר נוצלה:
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)) }
במקרים שבהם צריך את ה-insets הגולמיים של החלון בלי צריכה, משתמשים בערכים של WindowInsets ישירות, או משתמשים ב-WindowInsets.asPaddingValues() כדי להחזיר PaddingValues של ה-insets שלא מושפעים מהצריכה.
עם זאת, בגלל ההסתייגויות הבאות, עדיף להשתמש ב-modifiers של ריפוד מרווחי החלון וב-modifiers של גודל מרווחי החלון כשאפשר.
שלבי הוספת מרווחים ו-Jetpack Compose
Compose משתמש בממשקי ה-API הבסיסיים של AndroidX Core כדי לעדכן את ה-insets ולהוסיף להם אנימציה, והם משתמשים בממשקי ה-API הבסיסיים של הפלטפורמה שמנהלים את ה-insets. בגלל ההתנהגות הזו של הפלטפורמה, יש קשר מיוחד בין השוליים לבין השלבים של Jetpack Compose.
הערך של השוליים מתעדכן אחרי שלב הקומפוזיציה, אבל לפני שלב הפריסה. זה אומר שבדרך כלל, כשקוראים את הערך של ה-insets בקומפוזיציה, משתמשים בערך של ה-insets שמאחר בפריים אחד. המשתנים המובְנים שמתוארים בדף הזה נועדו לעכב את השימוש בערכים של ה-insets עד לשלב הפריסה, כדי להבטיח שהערכים של ה-insets ישמשו באותו פריים שבו הם מתעדכנים.