支持多窗口模式

במצב 'חלונות מרובים', כמה אפליקציות יכולות לשתף את אותו מסך בו-זמנית. אפשר להציג אפליקציות זו לצד זו או אחת מעל השנייה (מצב מסך מפוצל), אפליקציה אחת בחלון קטן שמופיע מעל אפליקציות אחרות (מצב 'תמונה בתוך תמונה') או אפליקציות נפרדות בחלונות נפרדים שניתן להזיז ולשנות את הגודל שלהם (מצב חלונות במחשב).

איור 1. הצגת שתי אפליקציות זו לצד זו במצב מסך מפוצל.

הוראות למשתמש לגבי הגישה למצב מסך מפוצל בטלפונים מפורטות במאמר הצגת שתי אפליקציות בו-זמנית בטלפון Pixel.

תכונות ספציפיות לגרסה של ריבוי חלונות

חוויית המשתמש בחלונות מרובים תלויה בגרסת Android ובסוג המכשיר:

  • ב-Android 7.0 (רמת API 24) הושק מצב מסך מפוצל במכשירים עם מסך קטן ומצב תמונה בתוך תמונה במכשירים נבחרים.

    • מצב מסך מפוצל ממלא את המסך בשתי אפליקציות, שמוצגות זו לצד זו או אחת מעל השנייה. המשתמשים יכולים לגרור את המחיצה שמפרידה בין שתי האפליקציות כדי להגדיל את האחת ולהקטין את השנייה.

    • מצב 'תמונה בתוך תמונה' מאפשר למשתמשים להמשיך את הפעלת הסרטון תוך כדי אינטראקציה עם אפליקציה אחרת (מידע נוסף זמין במאמר תמיכה בתכונה 'תמונה בתוך תמונה').

    • יצרני מכשירים עם מסך גדול יכולים להפעיל את מצב חלונות במחשב, שבו המשתמשים יכולים לשנות את הגודל של כל פעילות באופן חופשי.

      כדי לקבוע איך האפליקציה תפעל במצב של חלונות מרובים, אפשר לציין את המימדים המינימליים המותרים של הפעילות. אפשר גם להשבית את מצב החלונות המרובים באפליקציה על ידי הגדרת resizeableActivity="false" כדי לוודא שהמערכת תמיד תציג את האפליקציה במסך מלא.

  • ב-Android 8.0 (רמת API 26) אפשר להשתמש במצב 'תמונה בתוך תמונה' במכשירים עם מסך קטן.

  • ב-Android 12 (רמת API ‏31) מצב חלונות מרובים הוא התנהגות רגילה.

    • במסכים גדולים (סיווג גודל חלון בינוני או מורחב), הפלטפורמה תומכת בכל האפליקציות במצב 'כמה חלונות בו-זמנית', ללא קשר להגדרות האפליקציה. אם הערך הוא resizeableActivity="false", האפליקציה מועברת למצב תאימות במקרה הצורך כדי להתאים למימדי המסך.

    • במסכים קטנים (סיווג גודל חלון קומפקטי), המערכת בודקת את הערכים של minWidth ו-minHeight של הפעילות כדי לקבוע אם אפשר להריץ אותה במצב של כמה חלונות. אם הערך הוא resizeableActivity="false", האפליקציה לא תופעל במצב של חלונות מרובים, ללא קשר לרוחב ולגובה המינימליים.

מצב מסך מפוצל

כדי להפעיל את מצב המסך המפוצל, המשתמשים מבצעים את הפעולות הבאות:

  1. פתיחת מסך 'אחרונים'
  2. מחליקים אפליקציה כדי להציג אותה
  3. לוחצים על סמל האפליקציה בסרגל הכותרת של האפליקציה.
  4. בוחרים באפשרות בתפריט של המסך המפוצל.
  5. בוחרים אפליקציה אחרת במסך 'מהזמן האחרון', או סוגרים את המסך 'מהזמן האחרון' ומפעילים אפליקציה אחרת.

כדי לצאת ממצב מסך מפוצל, המשתמשים גוררים את המחיצה בין החלונות לקצה המסך – למעלה או למטה, שמאלה או ימינה.

הפעלה של חלון סמוך

אם האפליקציה שלכם צריכה לגשת לתוכן דרך כוונה (intent), תוכלו להשתמש ב-FLAG_ACTIVITY_LAUNCH_ADJACENT כדי לפתוח את התוכן בחלון צמוד במסך מפוצל.

FLAG_ACTIVITY_LAUNCH_ADJACENT הוצג ב-Android 7.0 (רמת API ‏24) כדי לאפשר לאפליקציות שפועלות במצב מסך מפוצל להפעיל פעילויות בחלון הסמוך.

ב-Android 12L‏ (רמת API 32) ואילך, ההגדרה של הדגל הורחבה כדי לאפשר לאפליקציות שפועלות במסך מלא להפעיל מצב מסך מפוצל ואז להפעיל פעילויות בחלון הסמוך.

כדי להפעיל פעילות סמוכה, משתמשים ב-FLAG_ACTIVITY_LAUNCH_ADJACENT בשילוב עם FLAG_ACTIVITY_NEW_TASK, לדוגמה:

Kotlin

fun openUrlInAdjacentWindow(url:
String) { Intent(Intent.ACTION_VIEW).apply { data = Uri.parse(url)
addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT or Intent.FLAG_ACTIVITY_NEW_TASK)
 }.also { intent -> startActivity(intent) } }

Java

public void openUrlInAdjacentWindow(String url) {
  Intent intent = new Intent(Intent.ACTION_VIEW);
  intent.setData(Uri.parse(url));
  intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCH_ADJACENT | Intent.FLAG_ACTIVITY_NEW_TASK);
  startActivity(intent);
}

מחזור החיים של פעילות במצב ריבוי חלונות

מצב חלונות מרובים לא משנה את מחזור החיים של הפעילות. עם זאת, המצב של אפליקציות שממשיכות לפעול בכמה חלונות משתנה בגרסאות שונות של Android.

חזרה להקראה בכמה קטעים

בגרסת Android 10 (API ברמה 29) ואילך יש תמיכה בהפעלה מחדש של כמה משימות בו-זמנית – כל הפעילויות נשארות במצב RESUMED כשהמכשיר במצב חלונות מרובים. אפשר להשהות פעילות אם פעילות שקופה מופיעה מעל הפעילות או אם אי אפשר להתמקד בפעילות, למשל אם הפעילות נמצאת במצב תמונה בתוך תמונה. יכול להיות גם שאף פעילות לא תהיה במוקד תשומת הלב בזמן נתון, למשל אם חלונית ההתראות פתוחה. השיטה onStop() פועלת כרגיל: היא נקראת בכל פעם שפעילות מסוימת יוצאת מהמסך.

התכונה 'המשך מספר קטעים בו-זמנית' זמינה גם במכשירים נבחרים עם Android 9 (API ברמה 28). כדי להביע הסכמה לשימוש בהפעלה מחדש בכמה מכשירים במכשירי Android 9, מוסיפים את המטא-נתונים הבאים למניפסט:

<meta-data android:name="android.allow_multiple_resumed_activities" android:value="true" />

כדי לוודא שמכשיר מסוים תומך במטא-נתונים האלה של המניפסט, צריך לעיין במפרטי המכשיר.

Android 9

במצב של חלונות מרובים ב-Android 9 (רמת API 28) ובגרסאות ישנות יותר, רק הפעילות שבה המשתמש ביצע את האינטראקציה האחרונה פעילה בכל זמן נתון. הפעילות הזו נחשבת הפעילות העליונה, והיא הפעילות היחידה בסטטוס RESUMED. כל שאר הפעילויות הגלויות הן STARTED אבל לא RESUMED. עם זאת, המערכת נותנת לפעילויות האלה שגלויות אבל לא הומשכו עדיפות גבוהה יותר מאשר לפעילויות שלא גלויות. אם המשתמש יוצר אינטראקציה עם אחת מהפעילויות הגלויה, הפעילות הזו תתחדש והפעילות שהיתה בראש תעבור למצב STARTED.

כשיש כמה פעילויות בתוך תהליך אפליקציה פעיל אחד, הפעילות עם סדר z הגבוה ביותר ממשיכה והפעילויות האחרות מושהות.

שינויים בהגדרות

כשהמשתמש מעביר אפליקציה למצב חלונות מרובים, המערכת מעדכנת את הפעילות על שינוי בתצורה, כפי שמתואר בקטע טיפול בשינויים בתצורה. המצב הזה מתרחש גם כשהמשתמש משנה את גודל האפליקציה או מחזיר אותה למצב מסך מלא.

באופן מהותי, לשינוי הזה יש את אותן השלכות על מחזור החיים של הפעילות כמו כשהמערכת מעדכנת את האפליקציה שהמכשיר עבר מכיוון לאורך לכיוון לרוחב, אלא שהמידות של האפליקציה משתנות במקום רק להחליף אותן. הפעילות יכולה לטפל בשינוי ההגדרה בעצמה, או שהאפליקציה יכולה לאפשר למערכת למחוק את הפעילות וליצור אותה מחדש עם המאפיינים החדשים.

אם המשתמש משנה את גודל החלון ומגדיל אותו באחת מהמימדים, המערכת משנה את גודל הפעילות בהתאם לפעולה של המשתמש ומנפיקה שינויים בהגדרות לפי הצורך. אם יש עיכוב בציור באזורים שנחשפו לאחרונה, המערכת תמלא את האזורים האלה באופן זמני בצבע שצוין במאפיין windowBackground או במאפיין הסגנון windowBackgroundFallback שמוגדר כברירת מחדל.

גישה בלעדית למשאבים

כדי לתמוך בתכונה 'המשך בכמה משחקים בו-זמנית', צריך להשתמש בקריאה החוזרת של מחזור החיים onTopResumedActivityChanged().

פונקציית ה-callback מופעלת כשפעילות מסוימת מקבלת או מאבדת את המיקום העליון של הפעילות שהושבתה והופעלה מחדש. הדבר חשוב כשפעילות משתמשת במשאב יחיד (singleton) משותף, כמו המיקרופון או המצלמה:

Kotlin

override fun
onTopResumedActivityChanged(topResumed: Boolean) { if (topResumed) { // Top
resumed activity. // Can be a signal to re-acquire exclusive resources. } else {
// No longer the top resumed activity. } }

Java

@Override
public void onTopResumedActivityChanged(boolean topResumed) {
  if (topResumed) {
      // Top resumed activity.
      // Can be a signal to re-acquire exclusive resources.
  } else {
      // No longer the top resumed activity.
  }
}

חשוב לזכור שאפליקציה יכולה לאבד משאבים מסיבות אחרות, כמו הסרה של חומרה משותפת.

בכל מקרה, אפליקציה צריכה לטפל באירועים ובשינויים במצב שמשפיעים על המשאבים הזמינים בצורה חלקה.

באפליקציות שמשתמשות במצלמה, CameraManager.AvailabilityCallback#onCameraAccessPrioritiesChanged() מספק רמז שזה יכול להיות זמן טוב לנסות לקבל גישה למצלמה. השיטה הזו זמינה החל מגרסה 10 של Android (רמת API‏ 29).

חשוב לזכור ש-resizeableActivity=false לא מבטיח גישה בלעדית למצלמה, כי אפשר לפתוח אפליקציות אחרות שמשתמשות במצלמה במסכים אחרים.

איור 2. מצלמה במצב ריבוי חלונות.

האפליקציה לא חייבת לשחרר את המצלמה כשהיא מאבדת את המיקוד. לדוגמה, יכול להיות שתרצו להמשיך את התצוגה המקדימה של המצלמה בזמן שהמשתמש יוצר אינטראקציה עם האפליקציה העליונה ביותר שמופעלת כרגע. אין בעיה שהאפליקציה שלכם תמשיך להפעיל את המצלמה כשהיא לא האפליקציה העליונה ביותר שמופעלת כרגע, אבל היא צריכה לטפל כראוי במקרה של ניתוק. כשהאפליקציה העליונה שתמשיכו ממנה תרצה להשתמש במצלמה, היא תוכל לפתוח אותה והאפליקציה שלכם תאבד את הגישה. האפליקציה יכולה לפתוח מחדש את המצלמה כשהיא מקבלת שוב את המיקוד.

אחרי שאפליקציה מקבלת קריאה חוזרת (callback) מסוג CameraDevice.StateCallback#onDisconnected(), קריאות נוספות למכשיר המצלמה יגרמו להשלכת CameraAccessException.

למספר צגים

ב-Android 10 (רמת API‏ 29) יש תמיכה בפעילויות במסכים משניים. אם פעילות מסוימת פועלת במכשיר עם כמה מסכים, המשתמשים יכולים להעביר את הפעילות ממסך אחד למסך אחר. המשך מרובות רלוונטי גם בתרחישים של מסכים מרובים, שבהם כמה פעילויות יכולות לקבל קלט ממשתמש בו-זמנית.

אפליקציה יכולה לציין באיזה מסך היא צריכה לפעול כשהיא מופעלת או כשהיא יוצרת פעילות אחרת. ההתנהגות הזו תלויה במצב ההפעלה של הפעילות שמוגדר בקובץ המניפסט, ובדגלים ובאפשרויות של הכוונה שהוגדרו על ידי הישות שמפעילה את הפעילות. פרטים נוספים זמינים בכיתה ActivityOptions.

כשפעילות מועברת למסך משני, היא עשויה לעבור עדכון הקשר, שינוי גודל החלון ושינויים בהגדרות ובמשאבים. אם הפעילות מטפלת בשינוי ההגדרה, היא תקבל הודעה ב-onConfigurationChanged(). אחרת, הפעילות תופעל מחדש.

פעילות צריכה לבדוק את התצוגה הנוכחית ב-onCreate() ואת onConfigurationChanged() אם היא מטפלת בשינוי ההגדרות. חשוב לעדכן את המשאבים והפריסות כשהתצוגה משתנה.

אם מצב ההפעלה שנבחר לפעילות מאפשר כמה מופעים, הפעלה במסך משני עשויה ליצור מופע חדש של הפעילות. שתי הפעילויות יחודשו בו-זמנית.

איור 3. מספר מופעים של פעילות במספר מסכים.

מומלץ גם לקרוא על ממשקי ה-API למסכים מרובים שהוצגו ב-Android 8.0.

הקשר של הפעילות לעומת הקשר של האפליקציה

שימוש בהקשר הנכון הוא קריטי כשמשתמשים בכמה מסכים. כשאתם ניגשים למשאבים, הקשר של הפעילות (שמוצג) שונה מהקשר של האפליקציה (שלא מוצג).

הקשר של הפעילות מכיל מידע על המסך, והוא תמיד מותאם לאזור התצוגה שבו הפעילות מופיעה. כך תוכלו לקבל את המידע הנכון על צפיפות המסך או על מדדי החלון של האפליקציה. תמיד צריך להשתמש בהקשר הפעילות (או בהקשר אחר שמבוסס על ממשק המשתמש) כדי לקבל מידע על החלון או המסך הנוכחיים. השינוי הזה משפיע גם על חלק מממשקי ה-API של המערכת שמשתמשים במידע מההקשר (לדוגמה, סקירה כללית על הודעות Toast).

ההגדרות של חלון הפעילות והתצוגה של ההורה מגדירות את המשאבים וההקשר. כדי לקבל את התצוגה הנוכחית:

Kotlin

val activityDisplay = activity.getDisplay()

Java

Display activityDisplay = activity.getDisplay();

הצגת המדדים הנוכחיים של חלון הפעילות:

Kotlin

val windowMetrics = activity.getWindowManager().getCurrentWindowMetrics()

Java

WindowMetrics windowMetrics = activity.getWindowManager().getCurrentWindowMetrics();

אחזור מדדי החלון המקסימלי בהגדרת המערכת הנוכחית:

Kotlin

val maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics()

Java

WindowMetrics maximumWindowMetrics = activity.getWindowManager().getMaximumWindowMetrics();

מדדי החלון המקסימלי משמשים לביצוע חישובים, לבחירת פריסות או לקביעת גודל המשאבים שאתם רוצים לאחזר מראש. האפשרות הזו ב-onCreate() מאפשרת לכם לקבל את ההחלטות האלה לפני עיבוד הפריסה הראשון. אין להשתמש במדדים האלה כדי לתכנן את הפריסה של רכיבי תצוגה ספציפיים. במקום זאת, צריך להשתמש במידע מהאובייקט Configuration.

מגרעות במסך

למכשירים מתקפלים יכולה להיות גיאומטריה שונה של פתחי החיתוך במצב מקופל ובמצב פתוח. כדי למנוע בעיות שקשורות לחורים במסך, כדאי לעיין במאמר תמיכה בחלקים חתוכים במסך.

מסכים משניים

אפשר לקבל את המסכים הזמינים משירות המערכת DisplayManager:

Kotlin

val displayManager =
getSystemService(Context.DISPLAY_SERVICE) as DisplayManager val displays =
displayManager.getDisplays()

Java

DisplayManager displayManager = (DisplayManager) getSystemService(Context.DISPLAY_SERVICE);
Display[] displays = displayManager.getDisplays();

אפשר להשתמש בכיתה Display כדי לקבל מידע על מסך מסוים, כמו גודל המסך או דגלים שמציינים אם המסך מאובטח. עם זאת, אל תניחו שגודל התצוגה יהיה זהה לאזור התצוגה שהוקצה לאפליקציה. חשוב לזכור שבמצב ריבוי חלונות, האפליקציה תופסת חלק מהמסך.

איך בודקים אם אפשר להפעיל פעילות במסך:

Kotlin

val activityManager =
getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager val
activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context,
displayId, intent)

Java

ActivityManager activityManager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
boolean activityAllowed = activityManager.isActivityStartAllowedOnDisplay(context, displayId, intent);

לאחר מכן מפעילים את הפעילות במסך:

Kotlin

val options = ActivityOptions.makeBasic()
options.setLaunchDisplayId(targetDisplay.displayId) startActivity(intent,
options.toBundle())

Java

ActivityOptions options = ActivityOptions.makeBasic();
options.setLaunchDisplayId(targetDisplay.displayId);
startActivity(intent, options.toBundle());

תמיכה במספר מסכים

ב-Android יש תמיכה בתצוגה מרובת מסכים למקלדות תוכנה, למסכי רקע ולמרכזי אפליקציות.

מקלדת שמופיעה במסך

אפשר להציג מקלדת במסך משני אם המסך מוגדר לתמוך בקישורים למערכת. עורך שיטת הקלט מופיע באופן אוטומטי אם שדה טקסט מבקש קלט במסך הזה.

איור 4. מקלדת במסך משני.

טפט

ב-Android 10 (רמת API ‏29), אפשר להגדיר טפט במסכים משניים. המסגרת יוצרת מכונה נפרדת של WallpaperService.Engine לכל תצוגה. חשוב לוודא שהפנים של כל מנוע מצוירים בנפרד. מפתחים יכולים לטעון נכסים באמצעות הקשר התצוגה ב-WallpaperService.Engine#getDisplayContext(). בנוסף, חשוב לוודא שהקובץ WallpaperInfo.xml מגדיר את android:supportsMultipleDisplays="true".

איור 5. טפט בטלפון ובמסך המשני.

מרכזי אפליקציות

קטגוריה חדשה של מסנני כוונה, SECONDARY_HOME, מספקת פעילות ייעודית למסכים משניים. המופעים של הפעילות משמשים בכל המסכים שתומכים בסמלי המערכת, אחד לכל מסך.

<activity>
    ...
    <intent-filter>
        <category android:name="android.intent.category.SECONDARY_HOME" />
        ...
    </intent-filter>
</activity>

לפעילות צריך להיות מצב הפעלה שלא מונע כמה מופעים ויכול להתאים לגדלים שונים של מסכים. אסור להשתמש באפשרויות singleInstance או singleTask למצב ההפעלה.

לדוגמה, ההטמעה של AOSP ב-Launcher3 תומכת בפעילות SECONDARY_HOME.

איור 6. מרכז אפליקציות בעיצוב חדשני תלת-ממדי בטלפון.
איור 7. מרכז האפליקציות של Material Design במסך משני.

מדדי חלון

ב-Android 11 (רמת API ‏30) הוספנו את השיטות הבאות של WindowManager כדי לספק את גבולות האפליקציות שפועלות במצב ריבוי חלונות:

השיטות computeCurrentWindowMetrics() ו-computeMaximumWindowMetrics() בספריית WindowManager של Jetpack מציעות פונקציונליות דומה, אבל עם תאימות לאחור לגרסה 14 של API.

כדי לקבל מדדים של תצוגות שאינן התצוגה הנוכחית, מבצעים את הפעולות הבאות (כפי שמוצג בקטע הקוד):

  • יצירת הקשר של מודעה לרשת המדיה
  • יצירת הקשר של חלון לתצוגה
  • אחזור הערך של WindowManager של הקשר החלון
  • אחזור הערך של WindowMetrics של אזור התצוגה המקסימלי שזמין לאפליקציה

Kotlin

val windowMetrics =
context.createDisplayContext(display)
.createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
.getSystemService(WindowManager::class.java) .maximumWindowMetrics

Java

WindowMetrics windowMetrics = context.createDisplayContext(display)
                            .createWindowContext(WindowManager.LayoutParams.TYPE_APPLICATION, null)
                            .getSystemService(WindowManager.class)
                            .getMaximumWindowMetrics();

שיטות שהוצאו משימוש

השיטות getSize() ו-getMetrics() של Display הוצאו משימוש ברמת API 30 לטובת השיטות החדשות של WindowManager.

ב-Android 12 (רמת API ‏31) הוצאו משימוש השיטות DisplaygetRealSize() ו-getRealMetrics(), וההתנהגות שלהן עודכנה כדי להתקרב יותר להתנהגות של getMaximumWindowMetrics().

הגדרת מצב ריבוי חלונות

אם האפליקציה שלכם מטרגטת את Android 7.0 (רמת API ‏24) ואילך, תוכלו להגדיר את האופן שבו הפעילויות באפליקציה תומכות במצב 'חלונות מרובים', ואם הן תומכות בו בכלל. אפשר להגדיר מאפיינים במניפסט כדי לקבוע את הגודל ואת הפריסה. הגדרות המאפיינים של פעילות ברמה הבסיסית חלות על כל הפעילויות בתוך מקבץ המשימות שלה. לדוגמה, אם לפעילות ברמה הבסיסית יש את הערך android:resizeableActivity="true", אפשר לשנות את הגודל של כל הפעילויות ב-task stack. במכשירים גדולים מסוימים, כמו Chromebook, יכול להיות שהאפליקציה תפעל בחלון שניתן לשינוי הגודל גם אם מציינים את הערך android:resizeableActivity="false". אם הפעולה הזו גורמת לשגיאות באפליקציה, תוכלו להשתמש במסננים ב-Google Play כדי להגביל את הזמינות של האפליקציה במכשירים כאלה.

ברירת המחדל ב-Android 12 (רמת API ‏31) היא מצב ריבוי חלונות. במסכים גדולים (סיווג גודל חלון בינוני או מורחב), כל האפליקציות פועלות במצב חלונות מרובים, ללא קשר להגדרת האפליקציה. במסכים קטנים, המערכת בודקת את ההגדרות minWidth, minHeight ו-resizeableActivity של הפעילות כדי לקבוע אם אפשר להפעיל אותה במצב של חלונות מרובים.

resizeableActivity

כדי להפעיל או להשבית את מצב החלונות המרובים לגרסאות API ברמה 30 ומטה, מגדירים את המאפיין הזה באלמנט <activity> או <application> במניפסט:

<application
  android:name=".MyActivity"
  android:resizeableActivity=["true" | "false"] />;

אם המאפיין הזה מוגדר כ-true, אפשר להפעיל את הפעילות במצב מסך מפוצל ובמצב חלון במחשב. אם המאפיין מוגדר לערך false, לא תהיה תמיכה במצב של חלונות מרובים בפעילות. אם הערך הוא false והמשתמש מנסה להפעיל את הפעילות במצב חלונות מרובים, הפעילות תופסת את המסך המלא.

אם האפליקציה שלכם מטרגטת רמת API 24 ואילך, אבל לא ציינתם ערך למאפיין הזה, ערך ברירת המחדל של המאפיין הוא true.

אם האפליקציה שלכם מטרגטת רמת API ‏31 ואילך, המאפיין הזה פועל באופן שונה במסכים קטנים וגדולים:

  • מסכים גדולים (חלונות בקטגוריית גודל בינוני או מורחב): כל האפליקציות תומכות במצב 'כמה חלונות בו-זמנית'. המאפיין מציין אם אפשר לשנות את הגודל של פעילות. אם הערך הוא resizeableActivity="false", האפליקציה מועברת למצב תאימות כשצריך כדי להתאים למימדי המסך.
  • מסכים קטנים (סיווג גודל חלון קומפקטי): אם resizeableActivity="true" והרוחב והגובה המינימליים של הפעילות עומדים בדרישות של תצוגת חלונות מרובים, הפעילות תומכת במצב של תצוגת חלונות מרובים. אם הערך הוא resizeableActivity="false", הפעילות לא תומכת במצב של חלונות מרובים, ללא קשר לרוחב ולגובה המינימליים של הפעילות.

supportsPictureInPicture

מגדירים את המאפיין הזה בצומת <activity> במניפסט כדי לציין אם הפעילות תומכת במצב 'תמונה בתוך תמונה'.

<activity
  android:name=".MyActivity"
  android:supportsPictureInPicture=["true" | "false"] />

configChanges

כדי לטפל בעצמכם בשינויים בהגדרות של חלונות מרובים, למשל כשמשתמש משנה את גודל החלון, מוסיפים את המאפיין android:configChanges לצומת <activity> במניפסט של האפליקציה עם לפחות את הערכים הבאים:

<activity
  android:name=".MyActivity"
  android:configChanges="screenSize | smallestScreenSize
      | screenLayout | orientation" />

אחרי שמוסיפים את android:configChanges, הפעילות והקטעים מקבלים קריאה חוזרת (callback) ל-onConfigurationChanged() במקום להימחק ולהיווצר מחדש. לאחר מכן תוכלו לעדכן את התצוגות באופן ידני, לטעון מחדש את המשאבים ולבצע פעולות אחרות לפי הצורך.

<layout>

ב-Android 7.0 (רמת API 24) ואילך, אלמנט המניפסט <layout> תומך במספר מאפיינים שמשפיעים על האופן שבו פעילות מתנהגת במצב של חלונות מרובים:

  • android:defaultHeight, android:defaultWidth: הגובה והרוחב שמוגדרים כברירת מחדל לפעילות כשהיא מופעלת במצב חלון במחשב.

  • android:gravity: המיקום הראשוני של הפעילות כשהיא מופעלת במצב חלון במחשב. ברשימה של הכיתה Gravity מפורטים ערכים מתאימים.

  • android:minHeight, android:minWidth: הגובה והרוחב המינימליים של הפעילות במצב מסך מפוצל ובמצב חלון במחשב. אם המשתמש מזיז את המפצל במצב מסך מפוצל כדי להקטין את הפעילות לגודל קטן מהגודל המינימלי שצוין, המערכת תגזור את הפעילות לגודל המבוקש על ידי המשתמש.

בקוד הבא מוסבר איך לציין את המיקום והגודל שמוגדרים כברירת מחדל לפעילות, ואת הגודל המינימלי שלה כשהפעילות מוצגת במצב חלון במחשב:

<activity android:name=".MyActivity">
    <layout android:defaultHeight="500dp"
          android:defaultWidth="600dp"
          android:gravity="top|end|..."
          android:minHeight="450dp"
          android:minWidth="300dp" />
</activity>

מצב ריבוי חלונות בזמן הריצה

החל מגרסה Android 7.0, המערכת מציעה פונקציונליות שתומכת באפליקציות שאפשר להריץ במצב חלונות מרובים.

תכונות מושבתות במצב ריבוי חלונות

במצב חלונות מרובים, מערכת Android עשויה להשבית או להתעלם מתכונות שלא רלוונטיות לפעילות שמשתפת את מסך המכשיר עם פעילויות או אפליקציות אחרות.

בנוסף, חלק מאפשרויות ההתאמה האישית של ממשק המשתמש של המערכת מושבתות. לדוגמה, אפליקציות לא יכולות להסתיר את שורת הסטטוס אם הן פועלות במצב של כמה חלונות (ראו שליטה בחשיפה של רכיב הממשק של המערכת).

המערכת מתעלמת משינויים במאפיין android:screenOrientation.

שאילתות וקריאות חזרה (callbacks) במצב ריבוי חלונות

בכיתה Activity יש את השיטות הבאות לתמיכה במצב של חלונות מרובים:

  • isInMultiWindowMode(): מציין אם הפעילות מתבצעת במצב של חלונות מרובים.

  • isInPictureInPictureMode(): מציין אם הפעילות מתבצעת במצב 'תמונה בתוך תמונה'.

  • onMultiWindowModeChanged(): המערכת קוראת לשיטה הזו בכל פעם שהפעילות עוברת למצב של חלונות מרובים או יוצאת ממנו. המערכת מעבירה לשיטה את הערך true אם הפעילות נכנסת למצב של חלונות מרובים, או את הערך false אם הפעילות יוצאת ממצב של חלונות מרובים.

  • onPictureInPictureModeChanged(): המערכת קוראת ל-method הזה בכל פעם שהפעילות עוברת למצב 'תמונה בתוך תמונה' או יוצאת ממנו. המערכת מעבירה לשיטה את הערך true אם הפעילות נכנסת למצב 'תמונה בתוך תמונה', או את הערך false אם הפעילות יוצאת ממצב 'תמונה בתוך תמונה'.

בכיתה Fragment מוצגות גרסאות של רבות מהשיטות האלה, למשל Fragment.onMultiWindowModeChanged().

מצב תמונה בתוך תמונה

כדי להעביר פעילות למצב 'תמונה בתוך תמונה', צריך להפעיל את השיטה enterPictureInPictureMode(). השיטה הזו לא משפיעה אם המכשיר לא תומך במצב 'תמונה בתוך תמונה'. מידע נוסף זמין במאמר הוספת סרטונים באמצעות התכונה 'תמונה בתוך תמונה' (PiP).

פעילויות חדשות במצב ריבוי חלונות

כשאתם משיקים פעילות חדשה, אתם יכולים לציין שהפעילות החדשה תוצג לצד הפעילות הנוכחית, אם הדבר אפשרי. משתמשים בדגל הכוונה FLAG_ACTIVITY_LAUNCH_ADJACENT, שמורה למערכת לנסות ליצור את הפעילות החדשה בחלון סמוך, כך ששתי הפעילויות ישתפו את המסך. המערכת עושה כמיטב יכולתה כדי לעשות זאת, אבל לא מובטח שהיא תצליח.

אם המכשיר נמצא במצב חלון במחשב ואתם מריצים פעילות חדשה, תוכלו לציין את המאפיינים של הפעילות החדשה (המיקום במסך והמידות) באמצעות קריאה ל-ActivityOptions.setLaunchBounds(). השיטה לא משפיעה אם המכשיר לא במצב ריבוי חלונות.

ברמת API 30 ומטה, אם מפעילים פעילות בתוך סטאק משימות, הפעילות מחליפה את הפעילות במסך, ויורשת את כל המאפיינים שלה לגבי חלונות מרובים. אם רוצים להפעיל את הפעילות החדשה כחלון נפרד במצב חלונות מרובים, צריך להפעיל אותה בערימה חדשה של משימות.

ב-Android 12 (רמת API ‏31) אפשר לפצל את חלון המשימות של אפליקציה לכמה פעילויות. אתם קובעים איך האפליקציה תציג את הפעילויות שלה – במסך מלא, זו לצד זו או בערימה – על ידי יצירת קובץ תצורה מסוג XML או שליחת קריאות ל-Jetpack WindowManager API.

גרירה ושחרור

המשתמשים יכולים לגרור ולשחרר נתונים מפעילות אחת לפעילות אחרת בזמן ששתי הפעילויות משותפות במסך. (לפני Android 7.0, המשתמשים יכלו לגרור ולשחרר נתונים רק בפעילות אחת). כדי להוסיף במהירות תמיכה בקבלת תוכן שנמחק, אפשר להיעזר ב-API של DropHelper. במאמר הפעלת גרירה ושחרור מוסבר איך להשתמש בגרירה ושחרור.

כמה מופעים במקביל

לכל פעילות ברמה הבסיסית יש משימה משלה, שפועלת בתהליך נפרד ומוצגת בחלון משלה. כדי להפעיל מופע חדש של האפליקציה בחלון נפרד, אפשר להתחיל פעילויות חדשות באמצעות הדגל FLAG_ACTIVITY_NEW_TASK. אפשר לשלב את המאפיין הזה עם חלק מהמאפיינים של חלונות מרובים כדי לבקש מיקום ספציפי לחלון החדש. לדוגמה, אפליקציית שופינג יכולה להציג כמה חלונות כדי להשוות בין מוצרים.

ב-Android 12 (רמת API 31) אפשר להפעיל שני מופעים של פעילות זה לצד זה באותו חלון משימות.

אם רוצים לאפשר למשתמשים להפעיל מופע נוסף של האפליקציה ממרכז האפליקציות או מסרגל האפליקציות, צריך לוודא שהפעילות של מרכז האפליקציות מגדירה את הערך android:resizeableActivity="true" ולא משתמשת במצב הפעלה שמונע הפעלה של כמה מופעים. לדוגמה, אפשר ליצור מופע של פעילות singleInstancePerTask כמה פעמים במשימות שונות כשמגדירים את FLAG_ACTIVITY_MULTIPLE_TASK או את FLAG_ACTIVITY_NEW_DOCUMENT.

חשוב לא להתבלבל בין כמה מופעים לבין פריסה עם כמה חלוניות, כמו תצוגת רשימה-פרטים שמשתמשת ב-SlidingPaneLayout שפועלת בתוך חלון אחד.

חשוב לזכור שכאשר כמה מכונות פועלות בחלונות נפרדים במכשיר מתקפל, יכול להיות שמכונה אחת או יותר יישלחו לרקע אם המצב ישתנה. לדוגמה, נניח שמכשיר פתוח ושיש בו שני מופעים של אפליקציה שפועלים בשני חלונות משני צידי המכשיר. אם המכשיר מקופל, יכול להיות שאחד מהמכונות יושבת במקום לנסות להתאים את החלונות של שתי המכונות למסך קטן יותר.

אימות במצב ריבוי חלונות

גם אם האפליקציה שלכם מטרגטת רמת API 24 ואילך וגם אם לא, כדאי לוודא איך היא מתנהגת במצב חלונות מרובים, למקרה שמשתמש ינסה להפעיל אותה במצב חלונות מרובים במכשיר עם Android מגרסה 7.0 ואילך.

בדיקת מכשירים

במכשירים עם Android מגרסה 7.0 (רמת API‏ 24) ואילך יש תמיכה במצב 'חלונות מרובים'.

רמת API ‏23 ומטה

כשמשתמשים מנסים להשתמש באפליקציה במצב ריבוי חלונות, המערכת משנה את גודל האפליקציה באופן גורף, אלא אם האפליקציה מצהירה על כיוון קבוע.

אם האפליקציה לא מצהירה על כיוון קבוע, צריך להפעיל אותה במכשיר עם Android מגרסה 7.0 ואילך ולנסות להעביר אותה למצב מסך מפוצל. מוודאים שחוויית המשתמש טובה גם כשמשנים את גודל האפליקציה באופן ידני.

אם האפליקציה מצהירה על כיוון מוצמד, צריך לנסות להעביר אותה למצב חלונות מרובים. מוודאים שהאפליקציה נשארת במצב מסך מלא.

רמות API 24 עד 30

אם האפליקציה שלכם מטרגטת לרמות API 24 עד 30 ולא משביתה את התמיכה בכמה חלונות, עליכם לוודא שההתנהגות הבאה מתרחשת גם במצב מסך מפוצל וגם במצב חלון במחשב:

  • פותחים את האפליקציה במסך מלא, ואז לוחצים לחיצה ארוכה על הלחצן מהזמן האחרון כדי לעבור למצב חלונות מרובים. מוודאים שהאפליקציה עוברת בצורה תקינה.

  • מריצים את האפליקציה ישירות במצב 'חלונות מרובים' ומוודאים שהיא מופעלת כמו שצריך. כדי להפעיל אפליקציה במצב ריבוי חלונות, לוחצים על הלחצן מהזמן האחרון, לוחצים לחיצה ארוכה על סרגל הכותרת של האפליקציה וגוררים אותו לאחד מהאזורים המודגשים במסך.

  • כדי לשנות את הגודל של האפליקציה במצב מסך מפוצל, גוררים את המחיצה במסך. מוודאים שהאפליקציה משתנה לגודל הרצוי בלי לקרוס, ושרכיבי ממשק המשתמש הנדרשים גלויים.

  • אם ציינת מידות מינימום לאפליקציה, נסו לשנות את גודל האפליקציה כך שגודל החלון שלה יהיה קטן יותר מהמידות האלה. מוודאים שלא ניתן לשנות את הגודל של האפליקציה כך שיהיה קטן מהמידות המינימליות שצוינו.

  • לאורך כל הבדיקות, מוודאים שהביצועים של האפליקציה תקינים. לדוגמה, מוודאים שאין עיכוב ארוך מדי עד לעדכון ממשק המשתמש אחרי שינוי הגודל של האפליקציה.

רמת API 31 ואילך

אם האפליקציה שלכם מטרגטת לרמת API 31 ואילך, והרוחב והגובה המינימליים של הפעילות הראשית קטנים או שווים למימדים המתאימים של אזור התצוגה הזמין, עליכם לוודא את כל ההתנהגויות שמפורטות לגבי רמות API 24 עד 30.

רשימת משימות לבדיקה

כדי לבדוק את הביצועים של האפליקציה במצב 'חלונות מרובים', כדאי לנסות את הפעולות הבאות. כדאי לנסות את הפעולות האלה גם במסך מפוצל וגם במצב חלון במחשב, אלא אם צוין אחרת.

  • כניסה למצב ריבוי חלונות ויציאה ממנו.

  • עוברים מהאפליקציה שלכם לאפליקציה אחרת, ומוודאים שהאפליקציה פועלת כראוי כשהיא גלויה אבל לא פעילה. לדוגמה, אם באפליקציה שלכם מופעל סרטון, עליכם לוודא שהסרטון ממשיך לפעול בזמן שהמשתמש מבצע פעולות באפליקציה אחרת.

  • במצב מסך מפוצל, אפשר לנסות להזיז את המפצל של המסך כדי להגדיל או להקטין את האפליקציה. כדאי לנסות את הפעולות האלה גם בצד לצד וגם אחת מעל השנייה בהגדרות. מוודאים שהאפליקציה לא קורסת, שהפונקציונליות החיונית גלויה ושפעולת שינוי הגודל לא נמשכת יותר מדי זמן.

  • ביצוע כמה פעולות שינוי גודל ברצף מהיר. מוודאים שהאפליקציה לא קורסת או דולפת זיכרון. כלי הניתוח של הזיכרון ב-Android Studio מספק מידע על השימוש של האפליקציה בזיכרון (מידע נוסף זמין במאמר בדיקת השימוש של האפליקציה בזיכרון באמצעות כלי הניתוח של הזיכרון).

  • משתמשים באפליקציה באופן רגיל במספר הגדרות חלון שונות, ומוודאים שהאפליקציה פועלת כראוי. מוודאים שהטקסט קריא ושרכיבי ממשק המשתמש לא קטנים מדי ולא ניתן לבצע איתם אינטראקציה.

התמיכה בריבוי חלונות מושבתת

ברמות API 24 עד 30, אם השבתתם את התמיכה בכמה חלונות על ידי הגדרת android:resizeableActivity="false", עליכם להפעיל את האפליקציה במכשיר עם Android מגרסה 7.0 עד 11 ולנסות להעביר את האפליקציה למצב מסך מפוצל ולמצב חלון במחשב. מוודאים שהאפליקציה נשארת במצב מסך מלא.

מקורות מידע נוספים

מידע נוסף על תמיכה בריבוי חלונות ב-Android זמין במאמרים הבאים:

מומלץ לך * הערה: טקסט הקישור מוצג כש-JavaScript מושבת * מצב תאימות למכשיר * תמיכה בשינוי הגודל של מסך גדול * טיפול בשינויים בהגדרות