หน้าต่างเบลอ

ใน API สาธารณะของ Android 12 นั้นพร้อมให้ใช้งานเอฟเฟกต์การเบลอของหน้าต่าง (เช่น การเบลอพื้นหลังและการเบลอด้านหลัง) โปรดทราบว่าแม้ว่าคุณจะเห็นการเบลอของหน้าต่างหรือที่เรียกว่าการเบลอแบบข้ามหน้าต่างในโค้ด เอกสารประกอบสำหรับนักพัฒนาซอฟต์แวร์ หรือสัญลักษณ์ UI แต่การเบลอแบบข้ามหน้าต่างก็เหมือนกับการเบลอของหน้าต่าง

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

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

1

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

2

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

3

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

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

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

การดำเนินการ

OEM และพันธมิตร

การเบลอของหน้าต่างถูกปิดใช้งานโดยค่าเริ่มต้น หากต้องการเปิดใช้งานฟังก์ชันเบลอบนอุปกรณ์ ให้ทำดังนี้:

  • ตรวจสอบให้แน่ใจว่าอุปกรณ์สามารถรองรับโหลด GPU เพิ่มเติมได้ - การเบลอนั้นมีราคาแพง และในอุปกรณ์ระดับล่าง อาจทำให้เฟรมหลุดได้ เปิดใช้งานสิ่งนี้บนอุปกรณ์ที่มีพลังงาน GPU เพียงพอเท่านั้น
  • ตรวจสอบให้แน่ใจว่า librenderengine ของคุณใช้ตรรกะการเบลอ - เอ็นจิ้นการเรนเดอร์ Android 12 เริ่มต้นทำ แต่เอ็นจิ้นการเรนเดอร์ที่กำหนดเองใด ๆ ต้องใช้ตรรกะการเบลอนั้นเอง
  • เปิดใช้งานการเบลอโดยการตั้งค่า sysprop flinger ต่อไปนี้:
# enable surface flinger window blurs
PRODUCT_PROPERTY_OVERRIDES += \
       ro.surface_flinger.supports_background_blur=1

นักพัฒนาบุคคลที่สาม

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

  1. อุปกรณ์ใช้ Android 11 หรือต่ำกว่า เนื่องจากหน้าต่างเบลอใช้ได้เฉพาะในอุปกรณ์ Android 12 ขึ้นไป แอปจึงต้องใช้ทางเลือกประสบการณ์สำรองที่ไม่เบลอสำหรับอุปกรณ์ที่ใช้ Android 11 และต่ำกว่า
  2. อุปกรณ์ไม่ รองรับการเบลอของหน้าต่างเนื่องจากมีราคาแพง ดังนั้นอุปกรณ์ระดับล่างอาจตกเฟรมเมื่อเรนเดอร์ ในกรณีดังกล่าว แอปจะต้องมอบประสบการณ์การใช้งานสำรองแบบไม่เบลอ
  3. เซิร์ฟเวอร์ระบบ (เช่น ระหว่างโหมดประหยัดแบตเตอรี่ หรือเนื่องจากการตั้งค่าของนักพัฒนาหรือโหมดอุโมงค์) ปิดใช้งานการเบลอขณะใช้งานจริง

จุดที่ 2 และ 3 ด้านบนรายงานโดยผู้ฟังที่ลงทะเบียนกับ WindowManager.addCrossWindowBlurEnabledListener หากแอปของคุณใช้ API เบลอ ให้ลงทะเบียน Listener นี้และอัปเดต UI ของคุณทุกครั้งที่มีการเรียก Listener หากคุณต้องการใช้ UI อื่นสำหรับสถานะที่เปิดใช้งานการเบลอและการปิดใช้งานการเบลอ เมื่อลงทะเบียนแล้ว ผู้ฟังจะถูกเรียกทันทีเพื่อรายงานว่ามีการเปิดใช้การเบลออยู่หรือไม่

ใช้ฟังก์ชันเบลอโดยใช้วิธีการต่อไปนี้:

ตัวอย่างและที่มา

public class BlurActivity extends Activity {
   private final int mBackgroundBlurRadius = 150;
   private final Drawable mBackgroundDrawableWithBlur;
   private final Drawable mBackgroundDrawableNoBlur;

   private final int mBlurBehindRadius = 50;
   private final float mDimAmountWithBlur = 0.1f;
   private final float mDimAmountNoBlur = 0.6f;


   private Consumer<Boolean> mCrossWindowBlurEnabledListener = enabled -> {
       getWindow().setBackgroundDrawable(
               enabled ? mBackgroundDrawableWithBlur : mBackgroundDrawableNoBlur);
       getWindow().setDimAmount(enabled ? mDimAmountWithBlur : mDimAmountNoBlur);
   };

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

       mBackgroundDrawableWithBlur = getContext().getResources().getDrawable(
               R.drawable.window_background_with_blur);
       mBackgroundDrawableNoBlur = getContext().getResources().getDrawable(
               R.drawable.window_background_no_blur);

       if (Android version >= Android S) {
           getWindow().addFlags(
                   WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
           window.getAttributes().setBlurBehindRadius(mBlurBehindRadius);
           window.setBackgroundBlurRadius(mBackgroundBlurRadius);
           getWindow().getDecorView().addOnAttachStateChangeListener(
                                         new View.OnAttachStateChangeListener() {
                    @Override
                    public void onViewAttachedToWindow(View v) {
                        getWindowManager().addCrossWindowBlurEnabledListener(
                                                     blurEnabledListener);
                    }

                       @Override
                   public void onViewDetachedFromWindow(View v) {
                       getWindowManager().removeCrossWindowBlurEnabledListener(
                                                      blurEnabledListener);
                     }
           });
       }
       getWindow().addFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND);
   }

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

มีสองวิธีในการอนุญาตและไม่อนุญาตการเบลอของหน้าต่าง

  1. จาก UI:

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

  2. จากเทอร์มินัล (อุปกรณ์จะต้องถูกรูท):

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

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

เมื่อคุณเปิดใช้งานการเบลอสำหรับอุปกรณ์ของคุณ ให้พิจารณาว่าสิ่งอื่น ๆ เช่นโหมดประหยัดแบตเตอรี่หรืออุโมงค์มัลติมีเดียสามารถปิดใช้งานได้ การเบลอจะเปิดใช้งานเมื่อตรงตามเงื่อนไขที่จำเป็นทั้งหมด โดยได้รับการสนับสนุน และ ไม่มีอะไรปิดบัง หากต้องการดูว่าสถานะปัจจุบันของฟังก์ชันเบลอ "เปิดใช้งาน" อยู่หรือไม่ ให้ใช้คำสั่ง adb shell wm disable-blur

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

เพื่อให้แน่ใจว่าเวอร์ชันของฟีเจอร์เบลอทำงานตามที่คุณต้องการ ให้ใช้ตรรกะ UI เพื่อวาดองค์ประกอบ UI ใหม่ทุกครั้งที่มีการเปลี่ยนแปลง blurEnabled (ตามที่รายงานโดย addCrossWindowBlurEnabledListener )

  1. เปิด UI ที่มีการเบลอ
  2. ใช้ขั้นตอนที่กำหนดสำหรับ การเปิดและปิดการเบลอของหน้าต่าง จาก UI หรือโดย CLI
  3. ตรวจสอบว่า UI เปลี่ยนเป็นและจากแบบที่ไม่เบลอตามที่คาดไว้

การแก้ไขปัญหา

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

ไม่เบลอ

  • ตรวจสอบว่าเปิดใช้งานการเบลอ (และฮาร์ดแวร์ของคุณรองรับ) โดยใช้ CLI หรือไปที่ Settings

    1. ใช้คำสั่ง adb shell wm disable-blur ซึ่งจะพิมพ์ว่าอุปกรณ์นั้นรองรับการเบลอหรือไม่และเปิดใช้งานอยู่หรือไม่
    2. ไปที่ การตั้งค่า -> ระบบ -> ตัวเลือกสำหรับนักพัฒนา -> การเรนเดอร์ที่เร่งด้วยฮาร์ดแวร์ -> อนุญาตการเบลอระดับหน้าต่าง หากคุณไม่พบตัวเลือกในนั้น แสดงว่าอุปกรณ์ของคุณไม่รองรับการเบลอ
  • ตรวจสอบให้แน่ใจว่าคุณตั้งค่าสีพื้นหลังหน้าต่างโปร่งแสง สีพื้นหลังของหน้าต่างทึบจะซ่อน (ครอบคลุม) พื้นที่ที่เบลอ

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

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

ไม่มีมุมมน

  • กำหนดมุมโค้งมนโดยการตั้งค่าพื้นหลังหน้าต่างที่วาดได้ - Window#setBackgroundDrawable ซึ่งจะกำหนดโครงร่างของพื้นที่เบลอ

การอัปเดตตัวเลือกผู้พัฒนาไม่ได้เปิดใช้งานการเบลอ

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

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

  • ตรวจสอบให้แน่ใจว่าหน้าต่างของคุณถูกทำเครื่องหมายเป็นลอย - android:windowIsFloating
  • ตรวจสอบให้แน่ใจว่าคุณได้ตั้งค่าพื้นหลังหน้าต่างที่วาดได้ - Window#setBackgroundDrawable ซึ่งจะกำหนดโครงร่างของพื้นที่เบลอ

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

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