มัวหน้าต่าง

ใน Android 12 มี API สาธารณะพร้อมใช้งานสำหรับ การใช้เอฟเฟกต์การเบลอหน้าต่าง เช่น การเบลอพื้นหลังและการเบลอพื้นหลัง

ใช้การเบลอหน้าต่างหรือการเบลอขอบหน้าต่างเพื่อเบลอหน้าจอด้านหลัง หน้าต่างที่กำหนด การเบลอหน้าต่างมี 2 ประเภท ซึ่งสามารถใช้เพื่อให้ได้ เอฟเฟ็กต์ภาพ:

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

  • เบลอด้านหลัง ให้คุณเบลอทั้งหน้าจอด้านหลังหน้าต่าง (กล่องโต้ตอบ) เพื่อสร้างเอฟเฟกต์ระยะชัดลึก

เอฟเฟกต์ 2 อย่างนี้สามารถใช้แยกกันหรือใช้ร่วมกันได้ ดังที่ปรากฏในรูปต่อไปนี้

เบลอพื้นหลังเท่านั้น

a

เบลอด้านหลังเท่านั้น

เบลอด้านหลังและการเบลอพื้นหลัง

รูปที่ 1 เบลอพื้นหลังเท่านั้น (a), เบลอด้านหลังเท่านั้น (b), เบลอพื้นหลัง และเบลอด้านหลัง (c)

ฟีเจอร์เบลอหน้าต่างจะทำงานได้กับหน้าต่างทุกบาน ซึ่งหมายความว่า มีแอปอื่นอยู่หลังหน้าต่าง เอฟเฟ็กต์นี้ไม่เหมือนกับ เอฟเฟกต์ภาพเบลอ ซึ่งจะเบลอเนื้อหาภายในหน้าต่างเดียวกัน การเบลอหน้าต่างคือ ซึ่งมีประโยชน์สำหรับกล่องโต้ตอบ Bottom Sheet และหน้าต่างแบบลอยอื่นๆ

การใช้งาน

นักพัฒนาแอป

นักพัฒนาแอปต้องระบุรัศมีการเบลอเพื่อสร้างเอฟเฟกต์เบลอ รัศมีการเบลอจะควบคุมความเข้มของการเบลอ กล่าวคือ ยิ่งรัศมีสูง ยิ่งเบลอมากเท่าไหร่ การเบลอ 0 พิกเซลหมายความว่าไม่มีการเบลอ สำหรับการเบลอด้านหลัง รัศมี 20 พิกเซลจะทำให้มีระยะชัดลึกของภาพที่ดี รัศมีการเบลอ 80 พิกเซลจะเกิดเอฟเฟกต์กระจกน้ำแข็งเกาะที่ดี หลีกเลี่ยงการเบลอ รัศมีสูงกว่า 150 พิกเซล เนื่องจากจะส่งผลต่อประสิทธิภาพอย่างมาก

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

การเบลอพื้นหลัง

ใช้การเบลอพื้นหลังบนหน้าต่างแบบลอยเพื่อสร้างเอฟเฟกต์พื้นหลังของหน้าต่าง ซึ่งเป็นภาพเบลอของเนื้อหา หากต้องการเพิ่มพื้นหลังแบบเบลอให้กับหน้าต่าง ให้ทำดังนี้

  1. เรียก Window#setBackgroundBlurRadius(int) ไปยัง กำหนดรัศมีการเบลอพื้นหลัง หรือตั้งค่า R.attr.windowBackgroundBlurRadius ในธีมหน้าต่าง

  2. ตั้งค่า R.attr.windowIsTranslucent เป็นจริงเพื่อทำให้หน้าต่างโปร่งแสง ใช้การเบลอใต้หน้าต่าง พื้นผิว ดังนั้นหน้าต่างต้องโปร่งแสงเพื่อให้มองเห็นการเบลอ

  3. (ไม่บังคับ) เรียก Window#setBackgroundDrawableResource(int) เพื่อ เพิ่มพื้นหลังหน้าต่างสี่เหลี่ยมผืนผ้าซึ่งถอนออกได้สีโปร่งแสง หรือตั้งค่า R.attr.windowBackground ในธีมหน้าต่าง

  4. สำหรับหน้าต่างที่มีมุมโค้งมน ให้ระบุมุมโค้งมนสำหรับ พื้นที่ที่เบลอโดยการตั้งค่า ShapeDrawable โดยใช้มุมโค้งมน เป็นพื้นหลังของหน้าต่าง ซึ่งถอนออกได้

  5. จัดการสถานะเปิดใช้และปิดใช้การเบลอ โปรดดูหลักเกณฑ์การใช้การเบลอหน้าต่างในแอป สำหรับข้อมูลเพิ่มเติม

เบลอด้านหลัง

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

หากต้องการเบลอเนื้อหาด้านหลังหน้าต่าง ให้ทำตามขั้นตอนต่อไปนี้

  1. เพิ่ม FLAG_BLUR_BEHIND ที่ธงหน้าต่างเพื่อเปิดใช้การเบลอด้านหลัง หรือตั้งค่าในธีมหน้าต่าง R.attr.windowBlurBehindEnabled

  2. โทรหา WindowManager.LayoutParams#setBlurBehindRadius ถึง กำหนดรัศมีด้านหลัง หรือตั้งค่าในธีมหน้าต่าง R.attr.windowBlurBehindRadius

  3. หรือเลือกเสริมการหรี่แสงเสริม

  4. จัดการสถานะเปิดใช้และปิดใช้การเบลอ โปรดดูหลักเกณฑ์การใช้การเบลอหน้าต่างในแอป สำหรับข้อมูลเพิ่มเติม

หลักเกณฑ์การใช้การเบลอหน้าต่างในแอป

การรองรับการเบลอหน้าต่างจะขึ้นอยู่กับปัจจัยต่อไปนี้

  • เวอร์ชัน Android: API การเบลอหน้าต่างพร้อมใช้งานใน Android 12 และ สูงขึ้น ตรวจสอบ SDK ของอุปกรณ์เพื่อดูเวอร์ชัน Android

  • ประสิทธิภาพของกราฟิก: อุปกรณ์ที่มี GPU ที่มีประสิทธิภาพต่ำกว่าอาจเลือกที่จะไม่ทำ รองรับการเบลอหน้าต่าง

  • สถานะระบบ: เซิร์ฟเวอร์ของระบบอาจปิดใช้งานการเบลอหน้าต่างชั่วคราวใน เช่น ขณะอยู่ในโหมดประหยัดแบตเตอรี่ขณะเล่นวิดีโอ เนื้อหาวิดีโอต่างๆ หรือเนื่องจากนักพัฒนาซอฟต์แวร์ลบล้าง

หากต้องการให้แอปใช้งานร่วมกันได้กับ Android ทุกเวอร์ชัน อุปกรณ์ และสถานะของระบบ ให้ทำตามหลักเกณฑ์ต่อไปนี้

  • เพิ่ม Listener ผ่านทาง WindowManager#addCrossWindowBlurEnabledListener เพื่อแจ้งให้คุณทราบเมื่อเปิดหรือปิดใช้การเบลอหน้าต่าง นอกจากนี้ ใช้ WindowManager#isCrossWindowBlurEnabled เพื่อค้นหา เปิดใช้การเบลอหน้าต่างอยู่หรือไม่

  • ใช้พื้นหลังหน้าต่าง 2 เวอร์ชันเพื่อรองรับ หรือปิดใช้งานการเบลอหน้าต่าง

    เมื่อเปิดใช้การเบลอ พื้นหลังหน้าต่างควรโปร่งแสงเพื่อให้ ความเบลอที่มองเห็นได้ ในสถานะนี้ เมื่อปิดการเบลอ เนื้อหาในหน้าต่าง ทับซ้อนกับเนื้อหาของหน้าต่างที่ซ่อนอยู่โดยตรง ทำให้ หน้าต่างที่ทับซ้อนกัน อ่านได้น้อยลง เพื่อไม่ให้หน้าต่างเบลอ ปิดใช้อยู่ ให้ปรับเปลี่ยน UI ของแอปดังนี้

    • หากต้องการเบลอพื้นหลัง ให้เพิ่มอัลฟ่าของพื้นหลังหน้าต่าง ทำให้ระบายสีได้ ทำให้ดูคลุมเครือมากขึ้น

    • หากต้องการเบลอด้านหลัง ให้เพิ่มเลเยอร์สลัวโดยมีระดับแสงสลัวสูงขึ้น

ตัวอย่างการเบลอด้านหลังและการเบลอพื้นหลัง

ส่วนนี้แสดงตัวอย่างกิจกรรมที่ใช้การเบลอ ด้านหลังและพื้นหลัง

ตัวอย่างต่อไปนี้ของ MainActivity.java คือกล่องโต้ตอบที่มีการเบลอ ด้านหลังรัศมี 20 พิกเซล และรัศมีการเบลอพื้นหลัง 80 พิกเซล มี มุมโค้งมน ซึ่งกำหนดไว้ใน XML ในพื้นหลังหน้าต่างซึ่งถอนออกได้ ถูกต้อง จัดการ Android เวอร์ชันต่างๆ หลายอุปกรณ์ (ที่อาจจะไม่ รองรับการเบลอหน้าต่าง) และการเบลอรันไทม์ตามการเปิดใช้หรือปิดใช้การเปลี่ยนแปลง ช่วยให้มั่นใจได้ว่า เนื้อหาของกล่องโต้ตอบสามารถอ่านได้ภายใต้เงื่อนไขเหล่านั้นโดยการปรับ พื้นหลังของหน้าต่าง Alpha ที่ถอนออกได้และจำนวนการสลัวหน้าต่าง

public class MainActivity extends Activity {

    private final int mBackgroundBlurRadius = 80;
    private final int mBlurBehindRadius = 20;

    // We set a different dim amount depending on whether window blur is enabled or disabled
    private final float mDimAmountWithBlur = 0.1f;
    private final float mDimAmountNoBlur = 0.4f;

    // We set a different alpha depending on whether window blur is enabled or disabled
    private final int mWindowBackgroundAlphaWithBlur = 170;
    private final int mWindowBackgroundAlphaNoBlur = 255;

    // Use a rectangular shape drawable for the window background. The outline of this drawable
    // dictates the shape and rounded corners for the window background blur area.
    private Drawable mWindowBackgroundDrawable;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        mWindowBackgroundDrawable = getDrawable(R.drawable.window_background);
        getWindow().setBackgroundDrawable(mWindowBackgroundDrawable);

        if (buildIsAtLeastS()) {
            // Enable blur behind. This can also be done in xml with R.attr#windowBlurBehindEnabled
            getWindow().addFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND);

            // Register a listener to adjust window UI whenever window blurs are enabled/disabled
            setupWindowBlurListener();
        } else {
            // Window blurs are not available prior to Android S
            updateWindowForBlurs(false /* blursEnabled */);
        }

        // Enable dim. This can also be done in xml, see R.attr#backgroundDimEnabled
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
    }

    /**
     * Set up a window blur listener.
     *
     * Window blurs might be disabled at runtime in response to user preferences or system states
     * (e.g. battery saving mode). WindowManager#addCrossWindowBlurEnabledListener allows to
     * listen for when that happens. In that callback we adjust the UI to account for the
     * added/missing window blurs.
     *
     * For the window background blur we adjust the window background drawable alpha:
     *     - lower when window blurs are enabled to make the blur visible through the window
     *       background drawable
     *     - higher when window blurs are disabled to ensure that the window contents are readable
     *
     * For window blur behind we adjust the dim amount:
     *     - higher when window blurs are disabled - the dim creates a depth of field effect,
     *       bringing the user's attention to the dialog window
     *     - lower when window blurs are enabled - no need for a high alpha, the blur behind is
     *       enough to create a depth of field effect
     */
    @RequiresApi(api = Build.VERSION_CODES.S)
    private void setupWindowBlurListener() {
        Consumer<Boolean> windowBlurEnabledListener = this::updateWindowForBlurs;
        getWindow().getDecorView().addOnAttachStateChangeListener(
                new View.OnAttachStateChangeListener() {
                    @Override
                    public void onViewAttachedToWindow(View v) {
                        getWindowManager().addCrossWindowBlurEnabledListener(
                                windowBlurEnabledListener);
                    }

                    @Override
                    public void onViewDetachedFromWindow(View v) {
                        getWindowManager().removeCrossWindowBlurEnabledListener(
                                windowBlurEnabledListener);
                    }
                });
    }

    private void updateWindowForBlurs(boolean blursEnabled) {
        mWindowBackgroundDrawable.setAlpha(blursEnabled && mBackgroundBlurRadius > 0 ?
                mWindowBackgroundAlphaWithBlur : mWindowBackgroundAlphaNoBlur);
        getWindow().setDimAmount(blursEnabled && mBlurBehindRadius > 0 ?
                mDimAmountWithBlur : mDimAmountNoBlur);

        if (buildIsAtLeastS()) {
            // Set the window background blur and blur behind radii
            getWindow().setBackgroundBlurRadius(mBackgroundBlurRadius);
            getWindow().getAttributes().setBlurBehindRadius(mBlurBehindRadius);
            getWindow().setAttributes(getWindow().getAttributes());
        }
    }

    private static boolean buildIsAtLeastS() {
        return Build.VERSION.SDK_INT >= Build.VERSION_CODES.S;
    }
}

หากต้องการสร้างมุมโค้งมนสำหรับหน้าต่าง เราจะกำหนดพื้นหลังของหน้าต่างใน res/drawable/window_background.xml เป็น ShapeDrawable ที่มีมุมโค้งมน ที่มีรัศมี 20 dp ดังต่อไปนี้

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <corners android:radius="20dp"/>
    <solid android:color="#AAAAAA"/>
</shape>

หน้าต่างจะเบลอการเบลอเนื้อหาของหน้าต่างใต้กิจกรรมนั้น ภาพที่เบลอจะถูกวาดใต้หน้าต่างกิจกรรมนี้ ดังนั้น หน้าต่างกิจกรรมต้องโปร่งแสงเพื่อให้เบลอ มองเห็นได้ เพื่อให้หน้าต่างโปร่งแสง เราตั้งค่า R.attr.windowIsTranslucent ใน ธีมกิจกรรมดังนี้

<style name="Theme.BlurryDialog" parent="Theme.MaterialComponents.Dialog">
    <item name="android:windowIsTranslucent">true</item>
</style>

OEM และพาร์ทเนอร์

หากต้องการให้อุปกรณ์เบลอหน้าต่าง OEM ต้องประกาศว่าอุปกรณ์นั้น รองรับการเบลอหน้าต่าง

วิธีตรวจสอบว่าอุปกรณ์รองรับการเบลอหน้าต่างหรือไม่

  • ตรวจสอบว่าอุปกรณ์รองรับการทำงานของ GPU เพิ่มเติม อุปกรณ์ระดับล่าง อาจไม่สามารถรองรับโหลดเพิ่มเติม ซึ่งอาจทำให้เฟรมลดลงได้ เปิดใช้การเบลอหน้าต่างเฉพาะในอุปกรณ์ทดสอบที่มีกำลัง GPU เพียงพอ

  • หากคุณมีเครื่องมือการแสดงผลที่ปรับแต่งแล้ว โปรดตรวจสอบว่าเครื่องมือแสดงผล จะใช้ตรรกะการเบลอ Android 12 เริ่มต้น เครื่องมือการแสดงผล ใช้ตรรกะการเบลอใน BlurFilter.cpp

เมื่อแน่ใจว่าอุปกรณ์รองรับการเบลอหน้าต่างแล้ว ให้ตั้งค่าต่อไปนี้ ปุ่มพื้นผิว sysprop:

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

การตรวจสอบความถูกต้อง

เพื่อตรวจสอบว่าหน้าต่างแอปได้รับการจัดการอย่างเหมาะสมเมื่อสลับระหว่างการเบลอ เปิดใช้และเบลอสถานะปิดใช้ ให้ทำตามขั้นตอนต่อไปนี้

  1. เปิด UI ที่มีการเบลอ

  2. เปิดหรือปิดใช้การเบลอหน้าต่างโดยเปิดและปิดการเบลอหน้าต่าง

  3. ตรวจสอบว่า UI ของหน้าต่างเปลี่ยนเป็นและออกจากสถานะเบลอตามที่คาดไว้

เปิดและปิดการเบลอหน้าต่าง

หากต้องการทดสอบการแสดงผล UI หน้าต่างด้วยเอฟเฟกต์เบลอหน้าต่าง ให้เปิดใช้งาน หรือ ปิดใช้การเบลอโดยใช้วิธีใดวิธีหนึ่งต่อไปนี้

  • จากตัวเลือกสำหรับนักพัฒนาแอป ให้ทำดังนี้

    การตั้งค่า -> ระบบ -> ตัวเลือกสำหรับนักพัฒนาแอป -> การแสดงผลที่มีการเร่งด้วยฮาร์ดแวร์ -> อนุญาตการเบลอระดับหน้าต่าง

  • จากเทอร์มินัลในอุปกรณ์ที่รูท ให้ทำดังนี้

    adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them
    

วิธีตรวจสอบว่าอุปกรณ์ Android 12 ขึ้นไปรองรับ Windows หรือไม่ เรียกใช้การเบลอและระบุว่าเปิดใช้การเบลอหน้าต่างอยู่หรือไม่ adb shell wm disable-blur ในอุปกรณ์ที่รูท

การแก้ปัญหา

ใช้คำแนะนำต่อไปนี้เป็นแนวทางในการแก้ปัญหาระหว่างการตรวจสอบความถูกต้อง

ไม่มีการเบลอ

  • ตรวจสอบว่าการเบลอเปิดใช้อยู่และฮาร์ดแวร์ของคุณรองรับ โปรดดูหัวข้อเปิดและปิดการเบลอหน้าต่าง

  • ตรวจสอบว่าได้ตั้งค่าสีพื้นหลังของหน้าต่างโปร่งแสงแล้ว หน้าต่างที่ทึบแสง สีพื้นหลังจะซ่อนบริเวณที่เบลอ

อุปกรณ์ทดสอบไม่รองรับการเบลอหน้าต่าง

  • ทดสอบแอปพลิเคชันในโปรแกรมจําลอง Android 12 หากต้องการตั้งค่าโปรแกรมจําลอง Android โปรดดูตั้งค่าโปรแกรมจําลอง Android อุปกรณ์เสมือนของ Android ที่คุณสร้างด้วยโปรแกรมจำลองจะรองรับหน้าต่าง เบลอ

ไม่มีมุมโค้งมน

การอัปเดตตัวเลือกสำหรับนักพัฒนาซอฟต์แวร์ไม่ได้เปิดใช้การเบลอ

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

เบลอพื้นหลังที่วาดเต็มหน้าจอ ไม่ใช่ภายในขอบเขตของหน้าต่าง

ไม่มีการอัปเดตจากผู้ฟังบนหน้าจอ

  • ระบบอาจนำการอัปเดต Listener ไปใช้กับอินสแตนซ์หน้าต่างเก่า ตรวจสอบว่าหน้าต่างถูกทำลายและสร้างอีกครั้งด้วยสิทธิ์ที่ถูกต้องหรือไม่ อัปเดต Listener