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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

  • Android 16 (רמת API 36) מבטל את ההגבלות על כיוון המסך, יחס הגובה-רוחב ושינוי הגודל.

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

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

אסטרטגיות הטמעה

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

תמיכה במסך מפוצל ביוזמת המשתמש

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

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

מסך מפוצל אוטומטי (הפעלה סמוכה)

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

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

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) }
}

הטמעת פעילות (פיצול פעילויות באותה משימה)

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

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

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

Multi-resume

ב-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-order תופעל מחדש, והפעילויות האחרות יושהו.

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

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

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

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

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

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

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

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.
    }
}

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

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

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

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

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

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

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

מדדים של חלונות

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

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

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

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

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

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

הוצאנו משימוש את ה-methods ‏DisplaygetSize() ו-getMetrics() ברמת API‏ 30, לטובת ה-methods החדשים מסוג WindowManager.

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

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

אם האפליקציה שלכם מטרגטת את Android 7.0 (רמת API ‏24) ואילך, אתם יכולים להגדיר איך הפעילויות של האפליקציה תומכות במצב מרובה חלונות, או אם הן תומכות בו בכלל. אפשר להגדיר מאפיינים בקובץ המניפסט כדי לשלוט בגודל ובפריסה. הגדרות המאפיינים של פעילות הבסיס חלות על כל הפעילויות במקבץ המשימות שלה. לדוגמה, אם לפעילות הבסיס יש android:resizeableActivity="true", אז כל הפעילויות במקבץ הפעילויות של המשימה ניתנות לשינוי גודל. במכשירים גדולים יותר, כמו 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", הפעילות לא תומכת במצב מרובה חלונות, ללא קשר לרוחב ולגובה המינימליים של הפעילות.

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

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

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, הפעילות והקטעים מקבלים קריאה חוזרת אל 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.

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

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

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

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

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

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

המחלקה Fragment חושפת גרסאות של רבות מהשיטות האלה. לדוגמה, Fragment.onMultiWindowModeChanged().

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

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

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

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

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

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

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

גרירה ושחרור

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

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

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

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

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

ב-Android 15 (רמת API‏ 35) ומעלה, אפשר להשתמש ב-PROPERTY_SUPPORTS_MULTI_INSTANCE_SYSTEM_UI כדי להצהיר על תמיכה בריבוי מופעים. המאפיין הוא אות מפורש לממשק המשתמש של המערכת לחשוף אמצעי בקרה למשתמש כדי ליצור כמה מופעים של האפליקציה. המאפיין לא תלוי במצב ההפעלה, אבל צריך להשתמש בו רק כשמצב ההפעלה של פעילות או אפליקציה תואם למאפיין, למשל כשמצב ההפעלה הוא לא singleInstance.

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

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

גם אם האפליקציה שלכם מטרגטת רמת 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.

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

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

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

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

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

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

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

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

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

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

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