כיתות של גודל חלון הן קבוצה של נקודות עצירה מוגדרות מראש באזור התצוגה, שעוזרות בתכנון, בפיתוח ובבדיקה של פריסות רספונסיביות או פריסות עם התאמה דינמית. נקודות העצירה מאזנות בין פשטוּת הפריסה לבין הגמישות של אופטימיזציית האפליקציה לתרחישים ייחודיים.
סיווגים של גודל חלון מסווגים את אזור התצוגה שזמין לאפליקציה שלכם בתור קומפקטית, בינונית או מורחבת. הרוחב והגובה הזמינים מסווגים בנפרד, כך שבכל זמן נתון לאפליקציה יש שתי כיתות של גודל חלון – אחת לרוחב ואחת לגובה. בדרך כלל, הרוחב הזמין חשוב יותר מהגובה הזמין בגלל הנפוצות של גלילה אנכית, ולכן סביר להניח שסיווג גודל החלון לפי רוחב רלוונטי יותר לממשק המשתמש של האפליקציה.
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_width.png?authuser=1&hl=he)
![](https://developer.android.google.cn/static/develop/ui/compose/images/layouts/adaptive/window-size-classes/window_size_classes_height.png?authuser=1&hl=he)
כפי שמוצג בתרשים, נקודות הצירוף מאפשרות לכם להמשיך לחשוב על הפריסות במונחים של מכשירים והגדרות. כל נקודת עצירה של סיווג גודל מייצגת מקרה נפוץ בתרחישים אופייניים של מכשירים. זוהי נקודת התייחסות שימושית כשאתם מתכננים את הפריסות שמבוססות על נקודות העצירה.
קטגוריית גודל | נקודת עצירה (breakpoint) | ייצוג המכשיר |
---|---|---|
רוחב קומפקטי | width < 600dp | 99.96% מהטלפונים במצב לאורך |
רוחב בינוני | 600dp ≤ רוחב < 840dp | 93.73% מהטאבלטים בפריסה לאורך,
רוב המסכים הפנימיים הגדולים שנפתחים במצב לאורך |
רוחב מורחב | רוחב ≥ 840dp | 97.22% מהטאבלטים בפריסה לרוחב,
המסכים הפנימיים הגדולים ביותר בפורמט לרוחב כשהם פתוחים |
גובה קומפקטי | height < 480dp | 99.78% מהטלפונים בפריסה לרוחב |
גובה בינוני | 480dp ≤ גובה < 900dp | 96.56% מהטאבלטים במצב לרוחב,
97.59% מהטלפונים במצב לאורך |
גובה מורחב | גובה ≥ 900dp | 94.25% מהטאבלטים בפורמט לאורך |
יכול להיות שיהיה שימושי להציג חזותית את סיווג הגדלים כמכשירים פיזיים, אבל סיווג הגדלים של חלונות לא נקבע באופן מפורש לפי גודל המסך של המכשיר. כיתות של גודל חלון לא מיועדות לשימוש בלוגיקה מסוג isTablet. במקום זאת, הקטגוריות של גודל החלון נקבעות לפי גודל החלון שזמין לאפליקציה, ללא קשר לסוג המכשיר שבו האפליקציה פועלת. לכך יש שתי השלכות חשובות:
במכשירים פיזיים אין ערובה לגודל חלון ספציפי. יכולות להיות סיבות רבות לכך ששטח המסך שזמין לאפליקציה שלכם יהיה שונה מגודל המסך של המכשיר. במכשירים ניידים, מצב מסך מפוצל מאפשר לפצל את המסך בין שתי אפליקציות. ב-ChromeOS, אפשר להציג אפליקציות ל-Android בחלונות מסוג מחשב שאפשר לשנות את הגודל שלהם באופן שרירותי. במכשירים מתקפלים יכולים להיות שני מסכים בגדלים שונים, שאפשר לגשת אליהם בנפרד על ידי קיפול או פתיחת המכשיר.
הסיווג של גודל החלון יכול להשתנות במהלך חיי האפליקציה. כשהאפליקציה פועלת, שינויים בכיוון המכשיר, ביצוע משימות מרובות בו-זמנית וקיפול/פתיחה של המסך יכולים לשנות את כמות שטח המסך שזמין. כתוצאה מכך, סיווג גודל החלון הוא דינמי, וממשק המשתמש של האפליקציה צריך להתאים את עצמו בהתאם.
סיווגים של גודל חלון ממופים לנקודות העצירה של פריסת 'חומר' בפורמטים הקומפקטי, הבינוני והמורחב, כפי שמפורט בהנחיות לממשק משתמש ב-Material Design. אפשר להשתמש בקטגוריות של גודל חלון כדי לקבל החלטות ברמה גבוהה לגבי פריסת האפליקציה, למשל, להחליט אם להשתמש בפריסה קנונית ספציפית כדי לנצל את שטח המסך הנוסף.
אפשר לחשב את הערך הנוכחי
WindowSizeClass
באמצעות
WindowSizeClass#compute()
הפונקציה שסופקה על ידי Jetpack
ספריית windowManager. הדוגמה הבאה
מראה איך לחשב את סיווג גודל החלון ולקבל עדכונים בכל פעם
שינויים במחלקות של גודל החלון:
Kotlin
class MainActivity : Activity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. val container: ViewGroup = binding.container // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(object : View(this) { override fun onConfigurationChanged(newConfig: Configuration?) { super.onConfigurationChanged(newConfig) computeWindowSizeClasses() } }) computeWindowSizeClasses() } private fun computeWindowSizeClasses() { val metrics = WindowMetricsCalculator.getOrCreate().computeCurrentWindowMetrics(this) val width = metrics.bounds.width() val height = metrics.bounds.height() val density = resources.displayMetrics.density val windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED val widthWindowSizeClass = windowSizeClass.windowWidthSizeClass // COMPACT, MEDIUM, or EXPANDED val heightWindowSizeClass = windowSizeClass.windowHeightSizeClass // Use widthWindowSizeClass and heightWindowSizeClass. } }
Java
public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // ... // Replace with a known container that you can safely add a // view to where the view won't affect the layout and the view // won't be replaced. ViewGroup container = binding.container; // Add a utility view to the container to hook into // View.onConfigurationChanged(). This is required for all // activities, even those that don't handle configuration // changes. You can't use Activity.onConfigurationChanged(), // since there are situations where that won't be called when // the configuration changes. View.onConfigurationChanged() is // called in those scenarios. container.addView(new View(this) { @Override protected void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); computeWindowSizeClasses(); } }); computeWindowSizeClasses(); } private void computeWindowSizeClasses() { WindowMetrics metrics = WindowMetricsCalculator.getOrCreate() .computeCurrentWindowMetrics(this); int width = metrics.getBounds().width int height = metrics.getBounds().height() float density = getResources().getDisplayMetrics().density; WindowSizeClass windowSizeClass = WindowSizeClass.compute(width/density, height/density) // COMPACT, MEDIUM, or EXPANDED WindowWidthSizeClass widthWindowSizeClass = windowSizeClass.getWindowWidthSizeClass() // COMPACT, MEDIUM, or EXPANDED WindowHeightSizeClass heightWindowSizeClass = windowSizeClass.getWindowHeightSizeClass() // Use widthWindowSizeClass and heightWindowSizeClass. } }
בדיקת קטגוריות של גודל חלון
כשמבצעים שינויים בפריסה, כדאי לבדוק את התנהגות הפריסה בכל גדלי החלונות, במיוחד ברוחב של נקודות העצירה הקומפקטיות, הבינוניות והמורחבות.
אם יש לכם פריסה קיימת למסכים קומפקטיים, כדאי לבצע אופטימיזציה של הפריסה לסיווג הגודל 'רוחב מורחב', כי סיווג הגודל הזה מספק את הכי הרבה מקום לשינויים נוספים בתוכן ובממשק המשתמש. לאחר מכן, מחליטים איזה פריסה מתאימה לגודל 'רוחב בינוני'. מומלץ להוסיף פריסה ייעודית.
השלבים הבאים
למידע נוסף על השימוש בקטגוריות של גודל חלון כדי ליצור פריסות רספונסיביות או דינמיות, אפשר לעיין במאמרים הבאים:
בפריסות שמבוססות על 'כתיבה': תמיכה בגדלים שונים של מסכים
לפריסות שמבוססות על תצוגות: עיצוב רספונסיבי/אדפטיבי עם תצוגות
מידע נוסף על הגורמים שמשפיעים על איכות האפליקציה בכל המכשירים ובכל גדלי המסכים זמין במאמרים הבאים: