אחרי שמטרגטים ל-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.
כדי לטפל בחפיפות, אפשר להגיב לתוספות, שמציינות אילו חלקים במסך חופפים לממשק המשתמש של המערכת, כמו סרגל הניווט או שורת הסטטוס. החפיפה יכולה להיות הצגה מעל התוכן, אבל היא יכולה גם להודיע לאפליקציה על תנועות מובנות במערכת.
סוגי ה-inset שרלוונטיים להצגת האפליקציה מקצה לקצה הם:
מרווחים פנימיים של סרגלי המידע: הכי מתאימים לתצוגות שניתן ללחוץ עליהן ושסרגלי המידע לא צריכים להסתיר אותן.
הוספת מגרעת במסך: לאזורים שבהם יכולה להיות מגרעת במסך בגלל צורת המכשיר.
הוספות של תנועות מובנות במערכת: לאזורים של ניווט באמצעות תנועות שמשמשים את המערכת, והם בעדיפות גבוהה יותר מהאפליקציה.
הוספת סרגלי מידע
הסוג הנפוץ ביותר של הוספות הוא הוספות של סרגל המידע. הם מייצגים את האזור שבו ממשק המשתמש של המערכת מוצג בציר 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:
כמו במרווחים של סרגל המידע, אפשר למנוע חפיפה של המרווחים של התנועות המובנות במערכת באמצעות 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 Design ל-Android (com.google.android.material) שמבוססים על תצוגות מטפלים באופן אוטומטי במרווחים הפנימיים, כולל BottomAppBar, BottomNavigationView, NavigationRailView ו-NavigationView
עם זאת, AppBarLayout לא מטפל באופן אוטומטי ב-inset. מוסיפים
android:fitsSystemWindows="true"
כדי לטפל בתוספות העליונות.
איך מטפלים בתוספות באמצעות רכיבי 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נוספים ל-methodsetProtections. לפני שאתם עושים את זה, ודאו שwindow.isNavigationBarContrastEnforced = false. - אחרת, מגדירים את
window.isNavigationBarContrastEnforced = true.
טיפים נוספים
טיפים נוספים לטיפול בתוספות.
הגדרת תוכן בגלילה מקצה לקצה
מוודאים שהפריט האחרון ברשימה לא מוסתר על ידי סרגלי המידע ב-RecyclerView או ב-NestedScrollView, על ידי טיפול בתוספות והגדרת clipToPadding ל-false.
בסרטון הבא מוצג מכשיר RecyclerView כשהתצוגה מקצה לקצה מושבתת (מימין) ומופעלת (משמאל):
בקטע יצירת רשימות דינמיות באמצעות RecyclerView יש דוגמת קוד.
הצגת תיבות דו-שיח במסך מלא מקצה לקצה
כדי להציג תיבת דו-שיח במסך מלא מקצה לקצה, צריך להפעיל את enableEdgeToEdge בתיבת הדו-שיח.
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);
}
}
}
...
}
מקורות מידע נוספים
למידע נוסף על פריסה מקצה לקצה, אפשר לעיין במקורות המידע הבאים.
בלוגים
עיצוב
מסמכים אחרים
סרטונים