מסכי פתיחה

החל מ-Android 12,‏ API‏ SplashScreen מאפשר לאפליקציות להיפתח עם אנימציה, כולל תנועה בתוך האפליקציה בזמן ההפעלה, מסך פתיחה שבו מוצג סמל האפליקציה ומעבר לאפליקציה עצמה. ‫SplashScreen הוא Window ולכן הוא כולל Activity.

איור 1. מסך פתיחה.

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

בנוסף לשימוש ב-SplashScreen platform API, אפשר להשתמש גם בספריית התאימות SplashScreen שעוטפת את SplashScreen API.

איך מסך הפתיחה פועל

כשמשתמש מפעיל אפליקציה בזמן שהתהליך של האפליקציה לא פועל (הפעלה במצב התחלתי (cold start)) או שה-Activity לא נוצר (הפעלה במצב ביניים (Warm start)), האירועים הבאים מתרחשים:

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

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

מסך הפתיחה אף פעם לא מוצג במהלך הפעלה מתוך הזיכרון (Hot start).

רכיבים ומנגנונים של מסך הפתיחה

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

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

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

כדאי לשים לב לרכיבים הבאים שמוצגים באיור 2:

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

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

3 כמו בסמלים הניתנים להתאמה, שליש מהחלק הקדמי מוסתר.

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

מידות מסך הפתיחה

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

  • תמונה עם מיתוג: הגודל הנדרש הוא 200x80dp.
  • סמל האפליקציה עם רקע לסמל: הסמל צריך להיות בגודל 240x240dp ולהתאים לעיגול בקוטר 160dp.
  • סמל האפליקציה ללא רקע: הסמל צריך להיות בגודל 288x288dp ולהתאים לעיגול בקוטר 192dp.

לדוגמה, אם הגודל המלא של תמונה הוא ‎300×300 dp, הסמל צריך להיכנס לעיגול בקוטר של ‎200 dp. כל מה שמחוץ לעיגול הופך לבלתי נראה (מוסתר).

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

אנימציות במסך הפתיחה ורצף ההפעלה

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

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

תמונה שבה מוצג רצף ההפעלה ב-12 פריים רצופים, החל מהקשה על סמל מפעיל האפליקציות ועד למילוי המסך כשהוא גדל
איור 4. רצף ההשקה.
  1. אנימציית כניסה: אנימציה שמוצגת כשעוברים מתצוגת המערכת למסך הפתיחה. הוא מנוהל על ידי המערכת ואי אפשר להתאים אותו אישית.

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

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

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

הדרישות לגבי אנימציה במסך הפתיחה

מסך הפתיחה צריך לעמוד במפרטים הבאים:

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

  • צריך לוודא שהסמל המונפש עומד בדרישות הבאות:

    • פורמט: הסמל צריך להיות קובץ XML של AnimatedVectorDrawable (AVD).
    • מידות: סמל AVD צריך להיות גדול פי ארבעה מסמל דינמי, באופן הבא:
      • שטח הסמל צריך להיות 432dp – כלומר, פי ארבע משטח 108dp של סמל הניתן להתאמה לא מוסתר.
      • שני השלישים הפנימיים של התמונה גלויים בסמל של מרכז האפליקציות, והם צריכים להיות ברוחב של 288dp – כלומר, פי ארבע מ-72dp שמהווים את האזור הפנימי המוסתר של סמל אדפטיבי.
    • משך הזמן: מומלץ לא לחרוג מ-1,000 אלפיות השנייה בטלפונים. אפשר להשתמש בהפעלה מושהית, אבל היא לא יכולה להיות ארוכה מ-166 אלפיות השנייה. אם זמן ההפעלה של האפליקציה ארוך מ-1,000 אלפיות השנייה, כדאי להשתמש באנימציה חוזרת.
  • קובעים את הזמן המתאים להסתרת מסך הפתיחה, שמתרחש כשהאפליקציה מציירת את הפריימים הראשונים. אפשר להתאים אישית את ההגדרה הזו כמו שמתואר בקטע בנושא השארת מסך הפתיחה על המסך למשך תקופות ארוכות יותר.

משאבים של מסך פתיחה

איור 5. דוגמה ל-AVD.

מורידים את ערכת המתחילים לדוגמה, שכוללת הדגמה של יצירה, עיצוב וייצוא של אנימציה ל-AVD. היא כוללת את הפריטים הבאים:

  • קובץ הפרויקט של האנימציה ב-Adobe After Effects.
  • קובץ ה-XML הסופי של AVD שיוצא.
  • דוגמה של אנימציה ב-GIF.

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

במדיניות הפרטיות של Google מוסבר איך אנחנו מטפלים בנתונים בשירות הזה.

התאמה אישית של מסך הפתיחה באפליקציה

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

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

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

  • להשאיר אותו על המסך למשך זמן ארוך יותר.

  • התאמה אישית של האנימציה להסרת מסך הפתיחה.

שנתחיל?

ספריית הליבה SplashScreen מביאה את מסך הפתיחה של Android 12 לכל המכשירים מ-API 23. כדי להוסיף אותו לפרויקט, מוסיפים את הקטע הבא לקובץ build.gradle:

מגניב

dependencies {
    implementation "androidx.core:core-splashscreen:1.0.0"
}

Kotlin

dependencies {
    implementation("androidx.core:core-splashscreen:1.0.0")
}

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

אתם יכולים לציין את המאפיינים הבאים בערכת העיצוב Activity כדי להתאים אישית את מסך הפתיחה של האפליקציה. אם כבר הטמעתם מסך פתיחה מדור קודם שמשתמש במאפיינים כמו android:windowBackground, כדאי לספק קובץ משאבים חלופי ל-Android 12 ואילך.

  1. כדי למלא את הרקע בצבע יחיד ספציפי, משתמשים בערך windowSplashScreenBackground:

    <item name="android:windowSplashScreenBackground">@color/...</item>
    
  2. משתמשים בצירוף המקשים windowSplashScreenAnimatedIcon כדי להחליף את הסמל במרכז חלון ההתחלה.

    באפליקציות שמטרגטות רק את Android 12 (רמת API‏ 32), צריך לבצע את הפעולות הבאות:

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

    <item name="android:windowSplashScreenAnimatedIcon">@drawable/...</item>
    
  3. משתמשים בערך windowSplashScreenAnimationDuration כדי לציין את משך האנימציה של הסמל במסך הפתיחה. ההגדרה הזו לא משפיעה על הזמן בפועל שבו מסך הפתיחה מוצג, אבל אפשר לאחזר אותה כשמתאימים אישית את אנימציית היציאה של מסך הפתיחה באמצעות SplashScreenView.getIconAnimationDuration. מידע נוסף מפורט בקטע הבא בנושא הצגת מסך הפתיחה למשך זמן ארוך יותר.

    <item name="android:windowSplashScreenAnimationDuration">1000</item>
    
  4. משתמשים ב-windowSplashScreenIconBackgroundColor כדי להגדיר רקע מאחורי הסמל של מסך הפתיחה. זה שימושי אם אין מספיק ניגודיות בין הרקע של החלון לבין הסמל.

    <item name="android:windowSplashScreenIconBackgroundColor">@color/...</item>
    
  5. אפשר להשתמש ב-windowSplashScreenBrandingImage כדי להגדיר תמונה שתוצג בתחתית מסך הפתיחה. עם זאת, בהנחיות העיצוב מומלץ לא להשתמש בתמונה של מיתוג.

    <item name="android:windowSplashScreenBrandingImage">@drawable/...</item>
    
  6. אתם יכולים להשתמש ב-windowSplashScreenBehavior כדי לציין אם סמל האפליקציה יוצג תמיד במסך הפתיחה ב-Android בגרסה 13 ואילך. ערך ברירת המחדל הוא 0, והסמל מוצג במסך הפתיחה אם הפעילות שמופעלת מגדירה את splashScreenStyle ל-SPLASH_SCREEN_STYLE_ICON, או אם היא פועלת בהתאם להתנהגות המערכת אם הפעילות שמופעלת לא מציינת סגנון. אם אתם מעדיפים שלא יוצג אף פעם מסך פתיחה ריק, ושתמיד יוצג הסמל המונפש, צריך להגדיר את הערך icon_preferred.

    <item name="android:windowSplashScreenBehavior">icon_preferred</item>
    

הצגת מסך הפתיחה למשך תקופות ארוכות יותר

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

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

Kotlin

// Create a new event for the activity.
override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // Set the layout for the content view.
    setContentView(R.layout.main_activity)

    // Set up an OnPreDrawListener to the root view.
    val content: View = findViewById(android.R.id.content)
    content.viewTreeObserver.addOnPreDrawListener(
        object : ViewTreeObserver.OnPreDrawListener {
            override fun onPreDraw(): Boolean {
                // Check whether the initial data is ready.
                return if (viewModel.isReady) {
                    // The content is ready. Start drawing.
                    content.viewTreeObserver.removeOnPreDrawListener(this)
                    true
                } else {
                    // The content isn't ready. Suspend.
                    false
                }
            }
        }
    )
}

Java

// Create a new event for the activity.
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // Set the layout for the content view.
    setContentView(R.layout.main_activity);

    // Set up an OnPreDrawListener to the root view.
    final View content = findViewById(android.R.id.content);
    content.getViewTreeObserver().addOnPreDrawListener(
            new ViewTreeObserver.OnPreDrawListener() {
                @Override
                public boolean onPreDraw() {
                    // Check whether the initial data is ready.
                    if (mViewModel.isReady()) {
                        // The content is ready. Start drawing.
                        content.getViewTreeObserver().removeOnPreDrawListener(this);
                        return true;
                    } else {
                        // The content isn't ready. Suspend.
                        return false;
                    }
                }
            });
}

התאמה אישית של האנימציה להסרת מסך הפתיחה

אפשר להתאים אישית את האנימציה של מסך הפתיחה באמצעות Activity.getSplashScreen().

Kotlin

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    splashScreen.setOnExitAnimationListener { splashScreenView ->
        // Create your custom animation.
        val slideUp = ObjectAnimator.ofFloat(
            splashScreenView,
            View.TRANSLATION_Y,
            0f,
            -splashScreenView.height.toFloat()
        )
        slideUp.interpolator = AnticipateInterpolator()
        slideUp.duration = 200L

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.doOnEnd { splashScreenView.remove() }

        // Run your animation.
        slideUp.start()
    }
}

Java

@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    // ...

    // Add a callback that's called when the splash screen is animating to the
    // app content.
    getSplashScreen().setOnExitAnimationListener(splashScreenView -> {
        final ObjectAnimator slideUp = ObjectAnimator.ofFloat(
                splashScreenView,
                View.TRANSLATION_Y,
                0f,
                -splashScreenView.getHeight()
        );
        slideUp.setInterpolator(new AnticipateInterpolator());
        slideUp.setDuration(200L);

        // Call SplashScreenView.remove at the end of your custom animation.
        slideUp.addListener(new AnimatorListenerAdapter() {
            @Override
            public void onAnimationEnd(Animator animation) {
                splashScreenView.remove();
            }
        });

        // Run your animation.
        slideUp.start();
    });
}

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

Kotlin

// Get the duration of the animated vector drawable.
val animationDuration = splashScreenView.iconAnimationDuration
// Get the start time of the animation.
val animationStart = splashScreenView.iconAnimationStart
// Calculate the remaining duration of the animation.
val remainingDuration = if (animationDuration != null && animationStart != null) {
    (animationDuration - Duration.between(animationStart, Instant.now()))
        .toMillis()
        .coerceAtLeast(0L)
} else {
    0L
}

Java

// Get the duration of the animated vector drawable.
Duration animationDuration = splashScreenView.getIconAnimationDuration();
// Get the start time of the animation.
Instant animationStart = splashScreenView.getIconAnimationStart();
// Calculate the remaining duration of the animation.
long remainingDuration;
if (animationDuration != null && animationStart != null) {
    remainingDuration = animationDuration.minus(
            Duration.between(animationStart, Instant.now())
    ).toMillis();
    remainingDuration = Math.max(remainingDuration, 0L);
} else {
    remainingDuration = 0L;
}

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