אחרי שתגדירו טירגוט ל-SDK 35 ואילך במכשיר עם Android מגרסה 15 ואילך, האפליקציה תוצג מקצה לקצה. החלון מופיע לאורך כל רוחב המסך וגובהו, על ידי ציור מאחורי פסי המערכת. סרגי המערכת כוללים את שורת הסטטוס, את סרגל הכתוביות ואת סרגל הניווט.
באפליקציות רבות יש סרגל אפליקציות בחלק העליון. סרגל האפליקציות העליון אמור להגיע לקצה העליון של המסך ולהופיע מאחורי שורת הסטטוס. אפשר גם להגדיר שסרגל האפליקציות העליון יתכווץ לגובה של שורת המצב כשגוללים בתוכן.
בהרבה אפליקציות יש גם סרגל אפליקציה תחתון או סרגל ניווט תחתון. הסרגלים האלה צריכים להגיע גם לקצה התחתון של המסך ולהופיע מאחורי סרגל הניווט. אחרת, האפליקציות צריכות להציג תוכן גלילה מאחורי סרגל הניווט.
כשמטמיעים פריסה מקצה לקצה באפליקציה, חשוב לזכור את הנקודות הבאות:
- הפעלת תצוגה מקצה לקצה
- לטפל בחפיפות חזותיות.
- כדאי להציג מודעות גרפיות מאחורי סרגלי המידע של המערכת.
הפעלת תצוגה מקצה לקצה
אם האפליקציה שלכם מטרגטת ל-SDK 35 ואילך, התצוגה מקצה לקצה מופעלת באופן אוטומטי במכשירי Android 15 ואילך.
כדי להפעיל תצוגה מקצה לקצה בגרסאות קודמות של Android:
מוסיפים תלות בספרייה
androidx.activity
בקובץbuild.gradle
של האפליקציה או המודול:Kotlin
dependencies { val activity_version =
activity_version
// Java language implementation implementation("androidx.activity:activity:$activity_version") // Kotlin implementation("androidx.activity:activity-ktx:$activity_version") }Groovy
dependencies { def activity_version =
activity_version
// Java language implementation implementation 'androidx.activity:activity:$activity_version' // Kotlin implementation 'androidx.activity:activity-ktx:$activity_version' }מייבאים את פונקציית התוסף
enableEdgeToEdge
לאפליקציה:
כדי להפעיל את התצוגה מקצה לקצה באופן ידני, מקישים על enableEdgeToEdge
ב-onCreate
של Activity
. צריך לקרוא לה לפני setContentView
.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) { enableEdgeToEdge() super.onCreate(savedInstanceState) ... }
Java
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { EdgeToEdge.enable(this); super.onCreate(savedInstanceState); ... }
כברירת מחדל, enableEdgeToEdge()
הופך את סרגלי המערכת לשקופים, מלבד במצב ניווט עם 3 לחצנים, שבו סרגל הסטטוס מקבל שכבת-על שקופה. הצבעים של סמלי המערכת והמסך המפריד משתנים בהתאם לעיצוב המערכת – בהיר או כהה.
הפונקציה enableEdgeToEdge()
מצהירה באופן אוטומטי שהאפליקציה צריכה להיות ממוקמת מקצה לקצה, ומתאימה את הצבעים של שורות הסטטוס של המערכת.
כדי להפעיל תצוגה מקצה לקצה באפליקציה בלי להשתמש בפונקציה enableEdgeToEdge()
, תוכלו לעיין במאמר הגדרה ידנית של תצוגה מקצה לקצה.
טיפול בחפיפה באמצעות קטעי תמונה
חלק מהתצוגות של האפליקציה עשויות להופיע מאחורי סרגלי המידע של המערכת, כפי שמוצג באיור 3.
כדי לטפל בחפיפה, אפשר להגיב לקטעי הטקסט שמציינים אילו חלקים במסך חופפים לממשק המשתמש של המערכת, כמו סרגל הניווט או סרגל הסטטוס. 'חפיפה' יכולה להיות הצגה מעל התוכן, אבל היא יכולה גם להודיע לאפליקציה על תנועות מערכת.
סוגי הפריימים המתאימים לתצוגה מקצה לקצה של האפליקציה הם:
הוספה של רכיבים לתוך שורת הסטטוס: מתאים במיוחד לתצוגות שאפשר להקיש עליהן, ושאסור ששורת הסטטוס תסתיר אותן.
Display cutout insets (הצגת קטעי תמונה שמותאמים למגרעת במסך): לאזורים שבהם עשויה להיות מגרעת במסך בגלל צורת המכשיר.
הוספת שטח לתנועות מערכת: לאזורים של ניווט באמצעות תנועות שבהם המערכת משתמשת, ויש להם עדיפות על פני האפליקציה.
רכיבי מידע בתוך סרגל המידע
הוספת רכיבים לפס המערכת היא הסוג הנפוץ ביותר של הוספת רכיבים. הם מייצגים את האזור שבו מוצג ממשק המשתמש של המערכת בציר Z מעל האפליקציה. מומלץ להשתמש בהם כדי להזיז או להוסיף מרווח לתצוגות באפליקציה שאפשר להקיש עליהן, ושאסור שהסרגלים של המערכת יסתירו אותן.
לדוגמה, לחצן הפעולה הצף (FAB) באיור 3 מוסתר חלקית על ידי סרגל הניווט:
כדי למנוע חפיפה חזותית כזו במצב תנועות או במצב לחצנים, אפשר להגדיל את השוליים של התצוגה באמצעות getInsets(int)
עם WindowInsetsCompat.Type.systemBars()
.
בדוגמת הקוד הבאה מוסבר איך מטמיעים קטעי הטמעה של שורת הסטטוס:
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(fab) { v, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()) // Apply the insets as a margin to the view. This solution sets // only the bottom, left, and right dimensions, but you can apply whichever // insets are appropriate to your layout. You can also update the view padding // if that's more appropriate. v.updateLayoutParams<MarginLayoutParams> { leftMargin = insets.left bottomMargin = insets.bottom rightMargin = insets.right } // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(fab, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars()); // Apply the insets as a margin to the view. This solution sets only the // bottom, left, and right dimensions, but you can apply whichever insets are // appropriate to your layout. You can also update the view padding if that's // more appropriate. MarginLayoutParams mlp = (MarginLayoutParams) v.getLayoutParams(); mlp.leftMargin = insets.left; mlp.bottomMargin = insets.bottom; mlp.rightMargin = insets.right; v.setLayoutParams(mlp); // Return CONSUMED if you don't want want the window insets to keep passing // down to descendant views. return WindowInsetsCompat.CONSUMED; });
אם מחילים את הפתרון הזה על הדוגמה שמוצגת באיור 3, לא תהיה חפיפה חזותית במצב לחצן, כפי שמוצג באיור 4:
אותו הדבר חל על מצב ניווט באמצעות תנועות, כפי שמוצג באיור 5:
הצגת קטעי תמונה עם מגרעת במסך
בחלק מהמכשירים יש חריגות במסך. בדרך כלל, החלק החתוך נמצא בחלק העליון של המסך ונכלל בשורת הסטטוס. כשמסך המכשיר במצב לאורך, ייתכן שהחור יהיה בצד האנכי. בהתאם לתוכן שהאפליקציה מציגה במסך, כדאי להטמיע תוספת מרווח כדי למנוע חתימות על המסך, כי כברירת מחדל, האפליקציות יתכנתו את התצוגה כך שתכלול את החתימות האלה.
לדוגמה, במסכים רבים באפליקציות מוצגת רשימה של פריטים. אל תסתירו את הפריטים ברשימה באמצעות חריצי המסך או שורות המערכת.
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(binding.recyclerView) { v, insets -> val bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() or WindowInsetsCompat.Type.displayCutout() ) v.updatePadding( left = bars.left, top = bars.top, right = bars.right, bottom = bars.bottom, ) WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(mBinding.recyclerView, (v, insets) -> { Insets bars = insets.getInsets( WindowInsetsCompat.Type.systemBars() | WindowInsetsCompat.Type.displayCutout() ); v.setPadding(bars.left, bars.top, bars.right, bars.bottom); return WindowInsetsCompat.CONSUMED; });
כדי לקבוע את הערך של WindowInsetsCompat
, מחשבים את הפונקציה or של סוגי פס המערכת וחתימות המסך.
מגדירים את clipToPadding
כ-RecyclerView
כדי שהרווח יגולול עם פריטי הרשימה. כך הפריטים יוכלו לעבור מאחורי שורת הסטטוסים של המערכת כשהמשתמש גולל, כפי שמוצג בדוגמה הבאה.
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
app:layoutManager="androidx.recyclerview.widget.LinearLayoutManager" />
תנועות מובנות במערכת
קטעי ההכנסה של תנועות המערכת מייצגים את האזורים בחלון שבהם תנועות המערכת מקבלות עדיפות על פני האפליקציה. האזורים האלה מוצגים בכתום באיור 6:
בדומה לרכיבים הפנימיים של שורת המערכת, אפשר למנוע חפיפה בין הרכיבים הפנימיים של תנועות המערכת באמצעות getInsets(int)
עם WindowInsetsCompat.Type.systemGestures()
.
אפשר להשתמש בהוספות האלה כדי להזיז תצוגות שאפשר להחליק אותן מהקצוות או להוסיף להן שטח. תרחישים נפוצים לשימוש כוללים גיליון תחתון, החלקה במשחקים וקרוסלות שמוטמעות באמצעות ViewPager2
.
ב-Android מגרסה 10 ואילך, אזורי ההכנסה של תנועות המערכת מכילים קטע פנימי בתחתית המסך לתנועת הבית, וקטעים פנימיים ימינה ושמאלה לתנועות החזרה:
בדוגמת הקוד הבאה מוסבר איך מטמיעים רכיבי 'הכנסה של תנועות מערכת':
Kotlin
ViewCompat.setOnApplyWindowInsetsListener(view) { view, windowInsets -> val insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()) // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.updatePadding(insets.left, insets.top, insets.right, insets.bottom) // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. WindowInsetsCompat.CONSUMED }
Java
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> { Insets insets = windowInsets.getInsets(WindowInsetsCompat.Type.systemGestures()); // Apply the insets as padding to the view. Here, set all the dimensions // as appropriate to your layout. You can also update the view's margin if // more appropriate. view.setPadding(insets.left, insets.top, insets.right, insets.bottom); // Return CONSUMED if you don't want the window insets to keep passing down // to descendant views. return WindowInsetsCompat.CONSUMED; });
Material Components
רכיבים רבים של Android Material Components (com.google.android.material) מבוססי-תצוגה מטפלים באופן אוטומטי ברכיבי inset, כולל BottomAppBar
, BottomNavigationView
, NavigationRailView
ו-NavigationView
.
עם זאת, AppBarLayout
לא מטפל באופן אוטומטי בתמונות מוטמעות. מוסיפים את הערך android:fitsSystemWindows="true"
כדי לטפל בתמונות מוטמעות בחלק העליון.
איך מטפלים בהכנסות באמצעות רכיבי Material ב-Compose
שליחת מודעות מוטמעות עם תאימות לאחור
כדי להפסיק את שליחת הבקשות להוספת רכיבים לחזית התצוגה לתצוגות הצאצא ולהימנע מיותר ריפוד, אפשר לצרוך את הבקשות להוספת רכיבים לחזית התצוגה באמצעות הקבוע WindowInsetsCompat.CONSUMED
. עם זאת, במכשירים עם Android מגרסה 10 (API ברמה 29 ומטה), המערכת לא שולחת תצוגות מוטמעות לאחים ואחיות אחרי קריאה ל-WindowInsetsCompat.CONSUMED
, מה שעלול לגרום לחפיפה חזותית לא מכוונת.
כדי לוודא שה-insets נשלחים לאחים בכל הגרסאות הנתמכות של Android, צריך להשתמש ב-ViewGroupCompat#installCompatInsetsDispatch
לפני שמשתמשים ב-insets. הפונקציה זמינה ב-AndroidX Core ו-Core-ktx 1.16.0-alpha01 ואילך.
Kotlin
// Use the i.d. assigned to your layout's root view, e.g. R.id.main val rootView = findViewById(R.id.main) // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView)
Java
// Use the i.d. assigned to your layout's root view, e.g. R.id.main LinearLayout rootView = findViewById(R.id.main); // Call before consuming insets ViewGroupCompat.installCompatInsetsDispatch(rootView);
מצב אימרסיבי
יש תוכן שהכי כדאי לצפות בו במסך מלא, כדי לספק למשתמש חוויה מעט יותר immersive. אפשר להסתיר את שורת הסטטוס ואת שורת הסטטוס העליונה במצב צפייה immersive באמצעות הספריות WindowInsetsController
ו-WindowInsetsControllerCompat
:
Kotlin
val windowInsetsController = WindowCompat.getInsetsController(window, window.decorView) // Hide the system bars. windowInsetsController.hide(Type.systemBars()) // Show the system bars. windowInsetsController.show(Type.systemBars())
Java
Window window = getWindow(); WindowInsetsControllerCompat windowInsetsController = WindowCompat.getInsetsController(window, window.getDecorView()); if (windowInsetsController == null) { return; } // Hide the system bars. windowInsetsController.hide(WindowInsetsCompat.Type.systemBars()); // Show the system bars. windowInsetsController.show(WindowInsetsCompat.Type.systemBars());
למידע נוסף על הטמעת התכונה הזו, אפשר לעיין במאמר הסתרת שורת הסטטוס והסרגל העליון במצב מלא.
סמלים בסרגל המידע
קריאה ל-enableEdgeToEdge
מבטיחה שהצבעים של הסמלים בסרגל המערכת יתעדכנו כשהעיצוב של המכשיר ישתנה.
כשעוברים למצב צפייה מקצה לקצה, יכול להיות שתצטרכו לעדכן באופן ידני את צבעי הסמלים בסרגל המערכת כך שייצרו ניגודיות לרקע של האפליקציה. לדוגמה, כדי ליצור סמלים בהירים בשורת הסטטוס:
Kotlin
WindowCompat.getInsetsController(window, window.decorView) .isAppearanceLightStatusBars = false
Java
WindowCompat.getInsetsController(window, window.getDecorView()) .setAppearanceLightStatusBars(false);
הגנה על סרגל המידע
אחרי שהאפליקציה שלכם מטרגטת ל-SDK 35 ואילך, הצגה מקצה לקצה נאכפת. שורת הסטטוס של המערכת וסרגלי הניווט באמצעות תנועות הם שקופים, אבל סרגל הניווט עם שלושת הלחצנים הוא שקוף למחצה.
כדי להסיר את הגנה הרקע השקופה שמוגדרת כברירת מחדל של ניווט עם שלושה לחצנים, מגדירים את Window.setNavigationBarContrastEnforced
לערך false
.
טיפים נוספים
כדי לוודא שסרחי המערכת לא מסתירים את פריט הרשימה האחרון ב-RecyclerView
או ב-NestedScrollView
, צריך לטפל בהכנסות ולהגדיר את clipToPadding
לערך false
.
בסרטון הבא מוצג מכשיר RecyclerView
עם תצוגה מקצה לקצה מושבתת (שמאל) ומופעל (ימין):
בקטע יצירת רשימות דינמיות באמצעות RecyclerView מופיע קטע קוד לדוגמה.
מקורות מידע נוספים
מידע נוסף על WindowInsets
, על ניווט באמצעות תנועות ועל אופן הפעולה של תצוגות מפורטות זמין במאמרים הבאים:
- סרגל המערכת של Android
- טיפים לטיפול ב-Insets לאכיפת מלא מסך ב-Android 15
- פיתוח לעתיד של Android
- WindowInsets – רכיבי מעקב אחרי פריסות
- ניווט באמצעות תנועות: קצוות
- איך פועלים הרכיבים המוכנסים ב-Android?