אחרי שמטרגטים ל-SDK 35 ומעלה במכשיר עם Android 15 ומעלה, האפליקציה מוצגת מקצה לקצה. החלון מתפרש לכל הרוחב והגובה של התצוגה על ידי ציור מאחורי סרגלי המערכת. סרגלי המערכת כוללים את שורת הסטטוס, סרגל הכתוביות וסרגל הניווט.
באפליקציות רבות יש סרגל אפליקציה עליון. סרגל האפליקציות העליון צריך להימתח עד לקצה העליון של המסך ולהופיע מאחורי סרגל הסטטוס. אופציונלי, סרגל האפליקציות העליון יכול להתכווץ לגובה של שורת הסטטוס כשגוללים את התוכן.
בהרבה אפליקציות יש גם סרגל אפליקציות תחתון או סרגל ניווט תחתון. הסרגלים האלה אמורים להימתח גם לקצה התחתון של המסך ולהופיע מאחורי סרגל הניווט. אחרת, באפליקציות צריך להציג תוכן נגלל מאחורי סרגל הניווט.
כשמטמיעים פריסה מקצה לקצה באפליקציה, חשוב לזכור את הנקודות הבאות:
- הפעלת תצוגה מקצה לקצה
- כדי לשפר את חוויית המשתמש במכשירים שונים, כדאי להטמיע פריסות דינמיות.
- טיפול בחפיפות חזותיות
- כדאי להציג מסכי הצללה מאחורי סרגלי המערכת
הפעלת תצוגה מקצה לקצה
אם האפליקציה מטרגטת ל-SDK בגרסה 35 ואילך, התכונה 'מקצה לקצה' מופעלת אוטומטית במכשירי Android 15 ומעלה.
כדי להפעיל את התכונה 'מקצה לקצה' בגרסאות קודמות של Android, צריך להפעיל ידנית את enableEdgeToEdge ב-onCreate של Activity.
Kotlin
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
WindowCompat.enableEdgeToEdge(window)
...
}
Java
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
WindowCompat.enableEdgeToEdge(getWindow());
...
}
כברירת מחדל, enableEdgeToEdge() הופך את סרגלי המערכת לשקופים, חוץ ממצב ניווט ב-3 כפתורים שבו סרגל הניווט מקבל שכבת מסך שקופה למחצה. הצבעים של סמלי המערכת ושל שכבת המסך החצי שקופה מותאמים לפי העיצוב הבהיר או הכהה של המערכת.
כדי להפעיל תצוגה מקצה לקצה באפליקציה בלי להשתמש בפונקציה enableEdgeToEdge(), אפשר לעיין במאמר הגדרה ידנית של תצוגה מקצה לקצה.
שימוש בתמונות ממוזערות כדי לטפל בחפיפות
יכול להיות שחלק מהתצוגות באפליקציה יופיעו מאחורי סרגלי המערכת, כמו שמוצג באיור 3.
כדי לטפל בחפיפות, אפשר להגיב למרווחים פנימיים שקובעים אילו חלקים במסך חופפים לממשק המשתמש של המערכת, כמו סרגל הניווט או סרגל המצב. החיתוך יכול להיות הצגה מעל התוכן, אבל הוא יכול גם להודיע לאפליקציה על תנועות במערכת.
סוגי השוליים הפנימיים שרלוונטיים לתצוגה מקצה לקצה של האפליקציה:
שוליים פנימיים של סרגלי המערכת: הכי מתאים לתצוגות שאפשר להקיש עליהן ושסרגלי המערכת לא יכולים להסתיר אותן.
Display cutout insets: for areas where there may be a screen cutout due to the shape of the device.
שוליים פנימיים של תנועות מובנות במערכת: לאזורים של ניווט באמצעות תנועות שבהם המערכת משתמשת, ושיש להם עדיפות על פני האפליקציה שלכם.
שוליים פנימיים של סרגלי המערכת
השוליים הפנימיים של סרגל המערכת הם הסוג הנפוץ ביותר של שוליים פנימיים. הם מייצגים את האזור שבו ממשק המשתמש של המערכת מוצג בציר 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 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 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:
בדומה ל-insets של סרגל המידע, אפשר למנוע חפיפה של ה-insets של תנועות מובנות במערכת באמצעות getInsets(int) עם WindowInsetsCompat.Type.systemGestures().
אפשר להשתמש בהזחות האלה כדי להזיז או להוסיף ריווח לתצוגות שאפשר להחליק בהן כדי להרחיק אותן מהקצוות. דוגמאות לשימושים נפוצים: גיליונות תחתונים, החלקה במשחקים וקרוסלות שמוטמעות באמצעות ViewPager2.
ב-Android מגרסה 10 ואילך, אזורי ה-inset של תנועות מובנות במערכת כוללים inset תחתון לתנועת הבית, ו-inset ימני ושמאלי לתנועות החזרה:
בדוגמת הקוד הבאה אפשר לראות איך מטמיעים את המרווחים הפנימיים של תנועה מובנית במערכת:
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
רכיבי Material רבים מבוססי-תצוגות ב-Android (com.google.android.material) מטפלים באופן אוטומטי בתוספות, כולל BottomAppBar, BottomNavigationView, NavigationRailView ו-NavigationView.
עם זאת, AppBarLayout לא מטפל אוטומטית בתוספות. Add
android:fitsSystemWindows="true"
כדי לטפל בתוספות העליונות.
כאן אפשר לקרוא איך מטפלים ב-insets באמצעות רכיבי Material ב-Compose.
שליחת חריצים שתואמים לדורות קודמים
כדי למנוע שליחה של חלונות קטנים לתצוגות של ילדים ולמנוע ריווח יתר, אפשר להשתמש בקבוע WindowInsetsCompat.CONSUMED כדי להשתמש בחלונות קטנים. עם זאת, במכשירים שמופעלת בהם גרסה Android 10 (רמת API 29 ומטה), לא מתבצעת שליחה של insets לאחים אחרי קריאה של WindowInsetsCompat.CONSUMED, מה שיכול לגרום לחפיפה ויזואלית לא מכוונת.
כדי לוודא שהשוליים הפנימיים נשלחים לרכיבים באותה רמה בכל גרסאות Android הנתמכות, צריך להשתמש ב-ViewGroupCompat#installCompatInsetsDispatch לפני שמשתמשים בשוליים הפנימיים. האפשרות הזו זמינה ב-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);
מצב עשיר
הצגת תוכן מסוים במסך מלא מאפשרת למשתמשים ליהנות מחוויה סוחפת יותר. אפשר להסתיר את סרגלי המערכת כדי להפעיל מצב צפייה היקפית באמצעות הספריות 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 ואילך, התצוגה מקצה לקצה נאכפת.
סרגל הסטטוס של המערכת וסרגלי הניווט באמצעות תנועות הם שקופים, אבל סרגל הניווט עם שלושת הכפתורים הוא שקוף למחצה. כדי להגדיר את enableEdgeToEdge כתואם לדור הקודם, צריך להתקשר אליו.
עם זאת, יכול להיות שברירות המחדל של המערכת לא יתאימו לכל תרחישי השימוש. כדי להחליט אם להשתמש בסרגלי מערכת שקופים או שקופים למחצה, כדאי לעיין בהנחיות לעיצוב סרגלי מערכת ב-Android ובעיצוב מקצה לקצה.
יצירת סרגלי מערכת שקופים
כדי ליצור סרגל סטטוס שקוף, צריך לטרגט ל-Android 15 (SDK 35) ומעלה או לקרוא ל-enableEdgeToEdge() עם ארגומנטים שמוגדרים כברירת מחדל לגרסאות קודמות.
כדי ליצור סרגל ניווט שקוף באמצעות ניווט מחוות, צריך לטרגט ל-Android מגרסה 15 ומעלה או לקרוא ל-enableEdgeToEdge() עם ארגומנטים שמוגדרים כברירת מחדל לגרסאות קודמות. בסרגל הניווט עם שלושת הלחצנים, מגדירים את Window.setNavigationBarContrastEnforced ל-false, אחרת יוחל מסך חצי שקוף.
יצירת סרגלי מערכת שקופים
כדי ליצור סרגל סטטוס שקוף למחצה:
- צריך לעדכן את התלות ב-
androidx-coreלגרסה 1.16.0-beta01 ואילך - עוטפים את פריסת ה-XML בתגי
androidx.core.view.insets.ProtectionLayoutומקצים מזהה. - אפשר לגשת ל-
ProtectionLayoutבאופן פרוגרמטי כדי להגדיר הגנות, לציין את הצד וGradientProtectionעבור סרגל הסטטוס.
<androidx.core.view.insets.ProtectionLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/list_protection" android:layout_width="match_parent" android:layout_height="match_parent"> <ScrollView android:id="@+id/item_list" android:clipToPadding="false" android:layout_width="match_parent" android:layout_height="match_parent"> <!--items--> </ScrollView> </androidx.core.view.insets.ProtectionLayout>
findViewById<ProtectionLayout>(R.id.list_protection) .setProtections( listOf( GradientProtection( WindowInsetsCompat.Side.TOP, // Ideally, this is the pane's background color paneBackgroundColor ) ) )
חשוב לוודא שהערך של ColorInt שמועבר אל GradientProtection תואם לרקע של התוכן. לדוגמה, בפריסת רשימה-פרטים שמוצגת במכשיר מתקפל, יכול להיות שיהיו ערכי GradientProtections שונים בצבעים שונים עבור חלונית הרשימה וחלונית הפרטים.
לא ליצור סרגל ניווט באמצעות תנועות שקוף למחצה. כדי ליצור סרגל ניווט שקוף עם שלושה לחצנים, מבצעים אחת מהפעולות הבאות:
- אם כבר יש לכם פריסה שמוקפת בתג
ProtectionView, אתם יכולים להעביר עודColorProtectionאוGradientProtectionלשיטהsetProtections. לפני שמבצעים את הפעולה הזו, חשוב לוודא שwindow.isNavigationBarContrastEnforced = false. - אחרת, מגדירים את
window.isNavigationBarContrastEnforced = true. אם האפליקציה שלכם מתקשרתenableEdgeToEdge, window.isNavigationBarContrastEnforced = trueהיא ברירת המחדל.
טיפים נוספים
טיפים נוספים לטיפול בתמונות ממוזערות.
הצגת תוכן גלילה מקצה לקצה
כדי לוודא שהפריט האחרון ברשימה לא מוסתר על ידי סרגלי המערכת ב-RecyclerView או ב-NestedScrollView, צריך לטפל ב-insets ולהגדיר את clipToPadding ל-false.
בסרטון הבא מוצג RecyclerView עם תצוגה מקצה לקצה כשהיא מושבתת (מימין) ומופעלת (משמאל):
דוגמת קוד מופיעה בקטע יצירת רשימות דינמיות באמצעות RecyclerView.
הצגת תיבות דו-שיח במסך מלא מקצה לקצה
כדי להציג את תיבת הדו-שיח במסך מלא מקצה לקצה, קוראים ל-enableEdgeToEdge ב-Dialog.
Kotlin
class MyAlertDialogFragment : DialogFragment() {
override fun onStart(){
super.onStart()
dialog?.window?.let { WindowCompat.enableEdgeToEdge(it) }
}
...
}
Java
public class MyAlertDialogFragment extends DialogFragment {
@Override
public void onStart() {
super.onStart();
Dialog dialog = getDialog();
if (dialog != null) {
Window window = dialog.getWindow();
if (window != null) {
WindowCompat.enableEdgeToEdge(window);
}
}
}
...
}
מקורות מידע נוספים
מידע נוסף על מעבר מתצוגה רגילה לתצוגה מקצה לקצה
בלוגים
עיצוב
מאמרי עזרה אחרים
סרטונים