פריסות רספונסיביות או דינמיות מספקות חוויית משתמש אופטימלית ללא קשר לגודל המסך. הטמיעו פריסות רספונסיביות או מותאמות כדי לאפשר לאפליקציה מבוססת-הצגה לתמוך בכל הגדרות התצוגה, הכיוונים והגדלים, כולל הגדרות שניתן לשנות את הגודל שלהן, כמו מצב חלונות מרובים.
עיצוב דינמי
השלב הראשון בתמיכה במגוון גורמי צורה של מכשירים הוא ליצור פריסה רספונסיבית לשינויים בכמות שטח המסך שזמין לאפליקציה.
ConstraintLayout
הדרך הטובה ביותר ליצור פריסה רספונסיבית היא להשתמש ב-ConstraintLayout
בתור הפריסה הבסיסית של ממשק המשתמש. ConstraintLayout
מאפשר לציין את המיקום והגודל של כל תצוגה בהתאם ליחסים המרחביים עם תצוגות אחרות בפריסה. כך תוכלו להזיז את כל התצוגות ולשנות את הגודל שלהן יחד כשמרחב התצוגה ישתנה.
הדרך הקלה ביותר ליצור פריסה באמצעות ConstraintLayout
היא להשתמש בכלי לעריכת פריסות ב-Android Studio. בעזרת עורך הפריסה אפשר לגרור תצוגות חדשות לפריסה, להחיל אילוצים ביחס לתצוגות הורה ולתצוגות אחיות ולהגדיר מאפייני תצוגה – והכול בלי לערוך קובצי XML באופן ידני.
![](https://developer.android.google.cn/static/images/screens_support/layout-editor_2x.png?authuser=3&hl=he)
ConstraintLayout
.
מידע נוסף זמין במאמר יצירת ממשק משתמש רספונסיבי באמצעות ConstraintLayout.
רוחב וגובה רספונסיביים
כדי לוודא שהפריסה תהיה רספונסיבית למסכים בגדלים שונים, צריך להשתמש ב-wrap_content
, ב-match_parent
או ב-0dp (match constraint)
לרוחב ולגובה של רכיבי התצוגה במקום בערכי קוד מוגדרים מראש:
wrap_content
: התצוגה מגדירה את הגודל שלה בהתאם לתוכן שהיא מכילה.match_parent
: התצוגה מתרחבת ככל האפשר בתוך תצוגת ההורה.0dp (match constraint)
: ב-ConstraintLayout
, בדומה ל-match_parent
. התצוגה תופסת את כל המרחב הזמין במסגרת האילוצים שלה.
לדוגמה:
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/lorem_ipsum" />
באיור 4 מוצג איך הרוחב והגובה של TextView
משתנים כשרוחב המסך משתנה בהתאם לכיוון המכשיר.
![](https://developer.android.google.cn/static/images/screens_support/layout-match-parent_2x.png?authuser=3&hl=he)
TextView
רספונסיבי.
הרוחב של TextView
מוגדר כך שיתמלא כל המרחב הזמין (match_parent
), והגובה מוגדר כך שיהיה בדיוק בגודל הנדרש לגובה הטקסט שמכיל (wrap_content
). כך התצוגה יכולה להתאים למימדי תצוגה שונים ולכמויות טקסט שונות.
אם אתם משתמשים ב-LinearLayout
, תוכלו גם להרחיב את התצוגות הצאצאיות על סמך משקל הפריסה, כך שהתצוגות ימלאו את המרחב הזמין באופן יחסי. עם זאת, שימוש במשקלים ב-LinearLayout
בתצוגת עץ מחייב את המערכת לבצע כמה סבבים של פריסה כדי לקבוע את הגודל של כל תצוגה, וכתוצאה מכך הביצועים של ממשק המשתמש יואטו.
אפשר ליצור ב-ConstraintLayout
כמעט את כל הפריסות האפשריות ב-LinearLayout
בלי להשפיע על הביצועים, לכן צריך להמיר את ה-LinearLayout
המוטמע ל-ConstraintLayout
. לאחר מכן תוכלו להגדיר פריסות עם משקלים באמצעות שרשורי אילוצים.
עיצוב דינמי
הפריסה של האפליקציה תמיד צריכה להיות רספונסיבית לגדלים שונים של מסכים. עם זאת, גם פריסה רספונסיבית לא יכולה לספק את חוויית המשתמש הטובה ביותר בכל מכשיר או במסך במצב של חלונות מרובים. לדוגמה, סביר להניח שממשק המשתמש שעיצבתם לטלפון לא מספק חוויית משתמש אופטימלית בטאבלט. עיצוב רספונסיבי מספק פריסות חלופיות שמותאמות לגדלים שונים של מסכים.
SlidingPaneLayout לממשקי משתמש מסוג רשימה ופירוט
ממשק משתמש עם רשימה מפורטת מספק בדרך כלל חוויית משתמש שונה במסכים בגדלים שונים. במסכים גדולים, חלונית הרשימה וחלונית הפרטים בדרך כלל מוצגות זו לצד זו. כשבוחרים פריט ברשימה, פרטי הפריט מוצגים בחלונית הפרטים בלי לשנות את ממשק המשתמש – שתי החלוניות נשארות זו לצד זו. עם זאת, במסכים קטנים, שני החלונות מוצגים בנפרד, וכל אחד מהם תופס את כל אזור התצוגה. כשבוחרים פריט בחלונית הרשימה, חלונית הפרטים (שמכילה את פרטי הפריט שנבחר) מחליפה את חלונית הרשימה. ניווט חזרה מחליף את חלונית הפרטים ברשימה.
SlidingPaneLayout
מנהל את הלוגיקה לקביעת אילו משתי חוויות המשתמש מתאימה לגודל החלון הנוכחי:
<?xml version="1.0" encoding="utf-8"?>
<androidx.slidingpanelayout.widget.SlidingPaneLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/recycler_view"
android:layout_width="280dp"
android:layout_height="match_parent"
android:layout_gravity="start" />
<androidx.fragment.app.FragmentContainerView
android:id="@+id/nav_host_fragment"
android:name="androidx.navigation.fragment.NavHostFragment"
android:layout_width="300dp"
android:layout_height="match_parent"
android:layout_weight="1"
app:defaultNavHost="true"
app:navGraph="@navigation/item_navigation" />
</androidx.slidingpanelayout.widget.SlidingPaneLayout>
המאפיינים layout_width
ו-layout_weight
של שתי התצוגות המפורטות שמכילות את SlidingPaneLayout
קובעים את ההתנהגות של SlidingPaneLayout
. בדוגמה הזו, אם החלון גדול מספיק (רוחב של 580dp לפחות) כדי להציג את שתי התצוגות, החלונות יוצגו זה לצד זה. עם זאת, אם רוחב החלון קטן מ-580dp, החלונות מחליקים זה על גבי זה כדי לתפוס בנפרד את כל חלון האפליקציה.
אם רוחב החלון גדול מהרוחב המינימלי הכולל שצוין (580dp), אפשר להשתמש בערכים של layout_weight
כדי לקבוע את הגודל של שני החלונות באופן יחסי. בדוגמה, חלונית הרשימה תמיד רחבה ב-280dp כי אין לה משקל.
עם זאת, חלונית הפרטים תמיד ממלאת את כל המרחב האופקי מעבר ל-580dp בגלל ההגדרה layout_weight
של התצוגה.
משאבי פריסה חלופיים
כדי להתאים את עיצוב ממשק המשתמש לגדלים שונים של מסכים, אפשר להשתמש בפריסות חלופיות שמזוהות באמצעות מסנני משאבים.
![](https://developer.android.google.cn/static/images/screens_support/sizes-phone-tablet_2x.png?authuser=3&hl=he)
כדי לספק פריסות מותאמות אישית ספציפיות למסך, אפשר ליצור עוד תיקיות res/layout/
בקוד המקור של האפליקציה. יוצרים ספרייה לכל הגדרת מסך שדורשת פריסה שונה. לאחר מכן מוסיפים למנהל הקבצים layout
את המאפיין של הגדרת המסך (לדוגמה, layout-w600dp
למסכים עם רוחב זמין של 600dp).
מגדירי ההגדרה מייצגים את שטח התצוגה הגלוי שזמין לממשק המשתמש של האפליקציה. המערכת מביאה בחשבון את כל האלמנטים של עיצוב המערכת (כמו סרגל הניווט) ואת השינויים בהגדרות החלון (כמו מצב חלונות מרובים) כשהיא בוחרת את הפריסה של האפליקציה.
כדי ליצור פריסות חלופיות ב-Android Studio, אפשר לעיין בקטע שימוש באפשרויות פריסה שונות לאופטימיזציה למסכים שונים במאמר פיתוח ממשק משתמש באמצעות תצוגות.
מגדיר הרוחב הקטן ביותר
המאפיין smallest width (רוחב מינימלי) מאפשר לכם לספק פריסות חלופיות למסכים עם רוחב מינימלי שנמדד בפיקסלים שלא תלויים בדחיסות (dp).
תיאור גודל המסך כמדד dp מאפשר ל-Android ליצור פריסות שמיועדות למאפייני תצוגה ספציפיים, בלי צורך לדאוג לדחיסות פיקסלים שונות.
לדוגמה, אפשר ליצור פריסה בשם main_activity
שמותאמת לטלפונים ולטאבלטים על ידי יצירת גרסאות שונות של הקובץ בתיקיות שונות:
res/layout/main_activity.xml # For phones (smaller than 600dp smallest width) res/layout-sw600dp/main_activity.xml # For 7" tablets (600dp wide or wider)
המאפיין 'רוחב מינימלי' מציין את הצד הקטן ביותר מבין שני צידי המסך, ללא קשר לכיוון הנוכחי של המכשיר. כך אפשר לציין את גודל המסך הכולל שזמין לפריסת המודעות.
כך מתאימים ערכים אחרים של רוחב מינימלי לגודלי מסך רגילים:
- 320dp: מסך קטן של טלפון (240x320 ldpi, 320x480 mdpi, 480x800 hdpi וכו')
- 480dp: מסך טלפון גדול בגודל 12.7 ס"מ (480x800 mdpi)
- 600dp: טאבלט בגודל 7" (600x1024 mdpi)
- 720dp: טאבלט בגודל 10" (720x1280 mdpi, 800x1280 mdpi וכו')
בתרשים הבא מוצגת תצוגה מפורטת יותר של האופן שבו רוחב המסך ב-dp תואם לגדלים ולכיוונים שונים של המסך.
![](https://developer.android.google.cn/static/images/screens_support/layout-adaptive-breakpoints_2x.png?authuser=3&hl=he)
הערכים של המאפיין smallest width הם בפורמט dp, כי מה שחשוב הוא נפח שטח המסך שזמין אחרי שהמערכת מביאה בחשבון את צפיפות הפיקסלים (ולא את רזולוציית הפיקסלים הגולמיים).
הגדלים שציינתם באמצעות מגדירי המשאבים, כמו רוחב קטן ביותר, הם לא גדלי המסך בפועל. במקום זאת, הגדלים מציינים את הרוחב או הגובה ביחידות dp שזמינות לחלון של האפליקציה. יכול להיות שמערכת Android תשתמש בחלק מהמסך לממשק המשתמש של המערכת (כמו סרגל המערכת בתחתית המסך או שורת הסטטוס בחלק העליון), כך שחלק מהמסך לא יהיה זמין לפריסה שלכם. אם האפליקציה שלכם פועלת במצב של כמה חלונות, היא יכולה לגשת רק לגודל החלון שמכיל אותה. כשמשנים את גודל החלון, מתרחש שינוי בתצורה עם גודל החלון החדש, שמאפשר למערכת לבחור קובץ פריסה מתאים. לכן, בגדלים של מגדירי המשאבים שאתם מגדירים צריך לציין רק את השטח שנחוץ לאפליקציה. המערכת מביאה בחשבון את כל השטח שבו נעשה שימוש בממשק המשתמש של המערכת כשהיא מקצה שטח לפריסה שלכם.
מגדיר רוחב זמין
במקום לשנות את הפריסה לפי הרוחב הקטן ביותר של המסך, כדאי לשנות את הפריסה לפי רוחב או גובה המסך הזמינים. לדוגמה, כדאי להשתמש בפריסה של שתי חלוניות כשרוחב המסך הוא לפחות 600dp. הערך הזה עשוי להשתנות בהתאם לכיוון של המכשיר – לרוחב או לאורך. במקרה כזה, צריך להשתמש במאפיין המפריד available width באופן הבא:
res/layout/main_activity.xml # For phones (smaller than 600dp available width) res/layout-w600dp/main_activity.xml # For 7" tablets or any screen with 600dp available width # (possibly landscape phones)
אם הגובה הזמין הוא בעיה באפליקציה שלכם, תוכלו להשתמש במאפיין available height. לדוגמה, layout-h600dp
למסכים עם גובה מסך של לפחות 600dp.
מילות מפתח להגדרת כיוון
יכול להיות שתוכלו לתמוך בכל וריאציות הגודל באמצעות שילובים בלבד של המאפיינים הרוחב הקטן ביותר והרוחב הזמין, אבל יכול להיות שתרצו גם לשנות את חוויית המשתמש כשהמשתמש עובר בין כיוון לאורך לכיוון לרוחב.
לשם כך, אפשר להוסיף את המאפיינים port
או land
לשמות של ספריות הפריסה. חשוב לוודא שהמסננים של הכיוון מופיעים אחרי המסננים של הגודל.
לדוגמה:
res/layout/main_activity.xml # For phones res/layout-land/main_activity.xml # For phones in landscape res/layout-sw600dp/main_activity.xml # For 7" tablets res/layout-sw600dp-land/main_activity.xml # For 7" tablets in landscape
מידע נוסף על כל המאפיינים של הגדרת המסך זמין במאמר סקירה כללית על משאבי האפליקציה.
סיווגים של גודל חלון
כיתות של גדלי חלונות הן נקודות עצירה של שדה התצוגה שבעזרתן אפשר ליצור פריסות מסתגלות. נקודות הצירוף מגדירות את אזור התצוגה שזמין לאפליקציה בתור קומפקטית, בינונית או מורחבת. הרוחב והגובה מצוינים בנפרד, כך שלאפליקציה תמיד יש סיווג של גודל חלון לרוחב וסיווג של גודל חלון לגובה.
כדי להחיל פריסות מותאמות באופן פרוגרמטי:
- יצירת משאבי פריסה על סמך נקודות העצירה של קטגוריות גודל החלון
- חישוב של הכיתות של גודל החלון לגובה ולרוחב של האפליקציה באמצעות הפונקציה
WindowSizeClass#compute()
מהספרייה Jetpack WindowManager - הרחבת משאב הפריסה לפי הקטגוריות של גודל החלון הנוכחי
מידע נוסף זמין במאמר סיווג חלונות.
רכיבי ממשק משתמש מודולריים באמצעות קטעים
כשאתם מתכננים את האפליקציה למספר גדלי מסכים, כדאי להשתמש בקטעים כדי לחלץ את הלוגיקה של ממשק המשתמש לרכיבים נפרדים, כדי לוודא שאתם לא מכפילים ללא צורך את התנהגות ממשק המשתמש בפעילויות שונות. לאחר מכן תוכלו לשלב את הקטעים כדי ליצור פריסות עם כמה חלונות במסכים גדולים, או למקם את הקטעים בפעילויות נפרדות במסכים קטנים.
לדוגמה, אפשר להטמיע את התבנית 'רשימת פרטים' (ראו SlidingPaneLayout למעלה) באמצעות קטע אחד שמכיל את הרשימה וקטע אחר שמכיל את פרטי הפריטים ברשימה. במסכים גדולים, אפשר להציג את הקטעים זה לצד זה. במסכים קטנים, אפשר להציג כל קטע בנפרד, כך שימלא את המסך.
מידע נוסף זמין בסקירה הכללית על קטעים.
הטמעת פעילות
אם האפליקציה מורכבת מכמה פעילויות, הטמעת הפעילות מאפשרת ליצור בקלות ממשק משתמש מותאם אישית.
הטמעת פעילות מאפשרת להציג כמה פעילויות או כמה מופעים של אותה פעילות בו-זמנית בחלון המשימות של האפליקציה. במסכים גדולים, הפעילויות יכולות להופיע זו לצד זו, ובמסכים קטנים, אחת מעל השנייה.
כדי לקבוע איך האפליקציה תציג את הפעילויות שלה, יוצרים קובץ תצורה של XML. המערכת משתמשת בקובץ הזה כדי לקבוע את אופן ההצגה המתאים על סמך גודל המסך. לחלופין, אפשר לבצע קריאות ל-Jetpack WindowManager API.
הטמעת הפעילות תומכת בשינויים בכיוון המכשיר ובמכשירים מתקפלים, וסדר הפעילויות יכול להשתנות כשהמכשיר מסתובב או מתקפל ונפתח.
מידע נוסף זמין במאמר הטמעת פעילות.
גדלים ויחסי גובה-רוחב של מסכים
כדאי לבדוק את האפליקציה במגוון גדלים של מסכים ויחסי גובה-רוחב כדי לוודא שהממשק המשתמש מתאים את עצמו בצורה נכונה.
ב-Android 10 (רמת API 29) ואילך יש תמיכה במגוון רחב של יחסי גובה-רוחב. גורמי הצורה של מכשירים מתקפלים יכולים להשתנות ממסכים ארוכים וצרים, כמו יחס גובה-רוחב של 21:9 כשמוסיפים את המסך, ועד ליחס גובה-רוחב ריבוע של 1:1 כשהמסך פתוח.
כדי להבטיח תאימות למכשירים רבים ככל האפשר, כדאי לבדוק את האפליקציות שלכם בכמה שיותר מיחסי הגובה-רוחב הבאים של המסך:
![](https://developer.android.google.cn/static/images/guide/topics/ui/foldables/fold-screen-ratios.png?authuser=3&hl=he)
אם אין לכם גישה למכשירים עם כל הגדלים השונים של המסכים שאתם רוצים לבדוק, תוכלו להשתמש במכונה וירטואלית ל-Android כדי לדמות כמעט כל גודל מסך.
אם אתם מעדיפים לבדוק במכשיר אמיתי אבל אין לכם מכשיר כזה, תוכלו להשתמש ב-Firebase Test Lab כדי לגשת למכשירים במרכז הנתונים של Google.
מקורות מידע נוספים
- Material Design – הסבר על הפריסה