หน้าจอแนะนำ

ตั้งแต่ Android 12 เป็นต้นไป SplashScreen API จะช่วยให้แอปเปิดตัว พร้อมภาพเคลื่อนไหว ซึ่งรวมถึงการเคลื่อนไหวเข้าแอปเมื่อเปิดตัว หน้าจอเริ่มต้น (Splash Screen) ที่แสดง ไอคอนแอป และการเปลี่ยนเข้าไปยังแอป A SplashScreen เป็น Window และ จึงครอบคลุม Activity

รูปที่ 1 หน้าจอแนะนำ

ประสบการณ์การใช้งานหน้าจอแนะนำจะนำองค์ประกอบการออกแบบมาตรฐานมาใช้กับการเปิดตัวแอปทุกครั้ง แต่คุณก็ปรับแต่งได้เพื่อให้แอปยังคงการสร้างแบรนด์ที่เป็นเอกลักษณ์ไว้ได้

นอกจากการใช้ SplashScreen Platform API แล้ว คุณยังใช้ SplashScreen ไลบรารี Compat ซึ่งครอบคลุม SplashScreen API ได้ด้วย

วิธีทำงานของหน้าจอแนะนำ

เมื่อผู้ใช้เปิดแอปขณะที่กระบวนการของแอปไม่ได้ทำงาน (a cold start) หรือไม่ได้สร้าง Activity (a warm start) เหตุการณ์ต่อไปนี้จะเกิดขึ้น

  1. ระบบจะแสดงหน้าจอแนะนำโดยใช้ธีมและภาพเคลื่อนไหวที่คุณกำหนด

  2. เมื่อแอปพร้อมแล้ว ระบบจะปิดหน้าจอแนะนำและแสดงแอป

หน้าจอแนะนำจะไม่แสดงระหว่าง Hot Start

องค์ประกอบและกลไกของหน้าจอแนะนำ

องค์ประกอบของหน้าจอแนะนำกำหนดโดยไฟล์ทรัพยากร XML ในไฟล์ Manifest ของ Android โดยแต่ละองค์ประกอบจะมีเวอร์ชันสำหรับโหมดสว่างและโหมดมืด

องค์ประกอบที่ปรับแต่งได้ของหน้าจอแนะนำประกอบด้วยไอคอนแอป พื้นหลังไอคอน และพื้นหลังหน้าต่าง

รูปภาพที่แสดงองค์ประกอบที่มีอยู่ในหน้าจอเริ่มต้น
รูปที่ 2 องค์ประกอบที่ปรับแต่งได้ของหน้าจอแนะนำ

พิจารณาองค์ประกอบต่อไปนี้ที่แสดงในรูปที่ 2

1 ไอคอนแอป ต้องเป็น Vector Drawable ซึ่งอาจเป็นภาพนิ่งหรือภาพเคลื่อนไหวก็ได้ แม้ว่าภาพเคลื่อนไหวจะมีระยะเวลาได้ไม่จำกัด แต่เราขอแนะนำว่าไม่ควรเกิน 1,000 มิลลิวินาที ไอคอน Launcher เป็นค่าเริ่มต้น

2 พื้นหลังไอคอน เป็นตัวเลือกและมีประโยชน์หาก คุณต้องการให้ไอคอนและพื้นหลังหน้าต่างมีความแตกต่างกันมากขึ้น หากคุณใช้ไอคอนแบบปรับอัตโนมัติ ระบบจะแสดงพื้นหลังของไอคอนหากมีความแตกต่างกับพื้นหลังหน้าต่างเพียงพอ

3 เช่นเดียวกับไอคอนแบบปรับอัตโนมัติ ระบบจะมาสก์พื้นหน้า 1 ใน 3 ของ

4 พื้นหลังหน้าต่าง ประกอบด้วยสีทึบสีเดียว หากตั้งค่าพื้นหลังหน้าต่างเป็นสีธรรมดา ระบบจะใช้สีนั้นโดยค่าเริ่มต้นหากไม่ได้ตั้งค่าแอตทริบิวต์

ขนาดหน้าจอแนะนำ

ไอคอนหน้าจอแนะนำใช้ข้อกำหนดเดียวกันกับ ไอคอนแบบปรับอัตโนมัติ, ดังนี้

  • รูปภาพที่มีการสร้างแบรนด์: ต้องมีขนาด 200x80 dp
  • ไอคอนแอปที่มีพื้นหลังไอคอน: ต้องมีขนาด 240x240 dp และพอดีกับวงกลมที่มีเส้นผ่านศูนย์กลาง 160 dp
  • ไอคอนแอปที่ไม่มีพื้นหลังไอคอน: ต้องมีขนาด 288x288 dp และพอดีกับวงกลมที่มีเส้นผ่านศูนย์กลาง 192 dp

ตัวอย่างเช่น หากรูปภาพมีขนาดเต็ม 300x300 dp ไอคอนต้องพอดีกับวงกลมที่มีเส้นผ่านศูนย์กลาง 200 dp ทุกอย่างที่อยู่นอกวงกลมจะมองไม่เห็น (มาสก์)

รูปภาพที่แสดงขนาดไอคอนต่างๆ สำหรับพื้นหลังแบบทึบและโปร่งใส
รูปที่ 3 ขนาดไอคอนหน้าจอแนะนำสำหรับ พื้นหลังทึบและพื้นหลังโปร่งใสตามลำดับ

ภาพเคลื่อนไหวหน้าจอแนะนำและลำดับการเปิดตัว

โดยทั่วไปแล้วการเปิดตัวแอปใน Cold Start มักจะใช้เวลาในการตอบสนองนานขึ้น การเพิ่มไอคอนเคลื่อนไหวลงในหน้าจอเริ่มต้น (Splash Screen) จะช่วยเพิ่มความสวยงามและมอบประสบการณ์การใช้งานที่ดียิ่งขึ้น การวิจัยผู้ใช้แสดงให้เห็นว่าเวลาเริ่มต้นที่รับรู้ได้จะน้อยลงเมื่อดูภาพเคลื่อนไหว

ภาพเคลื่อนไหวหน้าจอแนะนำจะฝังอยู่ในคอมโพเนนต์ลำดับการเปิดตัว ดังที่แสดงในรูปที่ 4

รูปภาพแสดงลำดับการเปิดแอปใน 12 เฟรมติดต่อกัน โดยเริ่มจากไอคอน Launcher ที่แตะและเติมเต็มหน้าจอขณะที่ขยาย
รูปที่ 4 ลำดับการเปิดตัว
  1. ภาพเคลื่อนไหวเข้า: ประกอบด้วยมุมมองระบบไปยังหน้าจอแนะนำ ซึ่งระบบจะควบคุมและปรับแต่งไม่ได้

  2. หน้าจอแนะนำ (แสดงในส่วน "รอ" ของลำดับ): คุณสามารถปรับแต่งหน้าจอแนะนำได้ ซึ่งจะช่วยให้คุณใส่ภาพเคลื่อนไหวโลโก้และการสร้างแบรนด์ของคุณเองได้ โดยหน้าจอแนะนำต้องเป็นไปตามข้อกำหนด ที่อธิบายไว้ในหน้านี้จึงจะทำงานได้อย่างถูกต้อง

  3. ภาพเคลื่อนไหวออก: ประกอบด้วยภาพเคลื่อนไหวที่ซ่อนหน้าจอแนะนำ หากต้องการปรับแต่ง ให้ใช้ SplashScreenView และ ไอคอน คุณสามารถเรียกใช้ภาพเคลื่อนไหวใดก็ได้ใน `SplashScreenView` โดยมีการตั้งค่าการแปลง ความทึบ และสี ในกรณีนี้ ให้นำหน้าจอแนะนำออกด้วยตนเองเมื่อภาพเคลื่อนไหวเสร็จสิ้น

เมื่อเรียกใช้ภาพเคลื่อนไหวไอคอน การเปิดตัวแอปจะให้ตัวเลือกในการข้ามลำดับในกรณีที่แอปพร้อมก่อน แอปจะทริกเกอร์ onResume() หรือหน้าจอแนะนำจะหมดเวลาโดยอัตโนมัติ ดังนั้นตรวจสอบว่าข้ามการเคลื่อนไหวได้อย่างสะดวก ระบบจะปิดหน้าจอแนะนำด้วย onResume() เท่านั้นเมื่อแอปเสถียรจากมุมมองภาพ จึงไม่จำเป็นต้องใช้ตัวหมุนเพิ่มเติม การแสดงอินเทอร์เฟซที่ไม่สมบูรณ์อาจทำให้ผู้ใช้รู้สึกไม่ดีและอาจทำให้รู้สึกว่าแอปคาดเดาไม่ได้หรือยังไม่สมบูรณ์

ข้อกำหนดของภาพเคลื่อนไหวหน้าจอแนะนำ

หน้าจอแนะนำต้องเป็นไปตามข้อกำหนดต่อไปนี้

  • ตั้งค่าสีพื้นหลังหน้าต่างสีเดียวโดยไม่มีความโปร่งใส ไลบรารีSplashScreen compat รองรับโหมดกลางวันและโหมดกลางคืน

  • ตรวจสอบว่าไอคอนเคลื่อนไหวเป็นไปตามข้อกำหนดต่อไปนี้

    • รูปแบบ: ไอคอนต้องเป็น XML ของ AnimatedVectorDrawable (AVD)
    • ขนาด: ไอคอน AVD ต้องมีขนาดเป็น 4 เท่าของไอคอนแบบปรับอัตโนมัติ ดังนี้
      • พื้นที่ไอคอนต้องมีขนาด 432 dp ซึ่งหมายความว่ามีขนาดเป็น 4 เท่าของพื้นที่ 108 dp ของไอคอนแบบปรับอัตโนมัติที่ไม่มีมาสก์
      • พื้นที่ 2 ใน 3 ด้านในของรูปภาพจะมองเห็นได้ในไอคอน Launcher และต้องมีขนาด 288 dp ซึ่งหมายความว่ามีขนาดเป็น 4 เท่าของ 72 dp ที่ประกอบขึ้นเป็นพื้นที่ด้านในที่มีมาสก์ของไอคอนแบบปรับอัตโนมัติ
    • ระยะเวลา: เราขอแนะนำว่าไม่ควรเกิน 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. Use 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 เพื่อระบุระยะเวลาของภาพเคลื่อนไหวไอคอนหน้าจอแนะนำ การตั้งค่านี้ จะไม่มีผลต่อเวลาจริงที่หน้าจอเริ่มต้น (Splash Screen) แสดง แต่คุณสามารถดึงข้อมูลนี้ได้เมื่อปรับแต่งภาพเคลื่อนไหวออกของหน้าจอเริ่มต้น (Splash Screen) โดยใช้ 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;
}

แหล่งข้อมูลเพิ่มเติม