ใน Android 12 API สาธารณะจะพร้อมใช้งานสำหรับการใช้เอฟเฟกต์การเบลอหน้าต่าง เช่น การเบลอพื้นหลังและการเบลอด้านหลัง
การเบลอหน้าต่างหรือการเบลอข้ามหน้าต่าง ใช้เพื่อเบลอหน้าจอด้านหลังหน้าต่างที่กำหนด การเบลอหน้าต่างมีสองประเภท ซึ่งสามารถใช้เพื่อให้ได้เอฟเฟ็กต์ภาพที่แตกต่างกัน:
การเบลอพื้นหลัง ช่วยให้คุณสร้างหน้าต่างที่มีพื้นหลังเบลอ ทำให้เกิดเอฟเฟกต์กระจกฝ้า
การเบลอด้านหลัง ทำให้คุณสามารถเบลอทั้งหน้าจอด้านหลังหน้าต่าง (กล่องโต้ตอบ) ทำให้เกิดเอฟเฟกต์ระยะชัดลึก
เอฟเฟกต์ทั้งสองสามารถใช้แยกกันหรือรวมกันได้ ดังแสดงในรูปต่อไปนี้:
ก | ข | ค |
รูปที่ 1 การเบลอพื้นหลังเท่านั้น (a) เบลอด้านหลังเท่านั้น (b) เบลอพื้นหลัง และเบลอด้านหลัง (c)
คุณลักษณะการเบลอหน้าต่างทำงานได้ทั่วทั้งหน้าต่าง ซึ่งหมายความว่าจะทำงานเมื่อมีแอปอื่นอยู่หลังหน้าต่างของคุณด้วย เอฟเฟกต์นี้ไม่เหมือนกับ เอฟเฟกต์การเรนเดอร์ภาพเบลอ ซึ่งจะเบลอเนื้อหา ภายใน หน้าต่างเดียวกัน การเบลอหน้าต่างมีประโยชน์สำหรับกล่องโต้ตอบ แผ่นงานด้านล่าง และหน้าต่างลอยอื่นๆ
การนำไปปฏิบัติ
นักพัฒนาแอป
นักพัฒนาแอปจะต้องระบุรัศมีการเบลอเพื่อสร้างเอฟเฟกต์การเบลอ รัศมีความเบลอจะควบคุมความหนาแน่นของความเบลอ กล่าวคือ ยิ่งรัศมีมากเท่าไร ความเบลอก็จะยิ่งหนาแน่นมากขึ้นเท่านั้น การเบลอ 0 px หมายความว่าไม่เบลอ สำหรับการเบลอด้านหลัง รัศมี 20 พิกเซลจะสร้างเอฟเฟกต์ระยะชัดลึกที่ดี ในขณะที่รัศมีเบลอพื้นหลัง 80 พิกเซลจะสร้างเอฟเฟกต์กระจกฝ้าที่ดี หลีกเลี่ยงรัศมีการเบลอที่สูงกว่า 150 พิกเซล เนื่องจากจะส่งผลต่อประสิทธิภาพอย่างมาก
เพื่อให้ได้เอฟเฟกต์เบลอที่ต้องการและเพิ่มความสามารถในการอ่าน ให้เลือกค่ารัศมีเบลอที่เสริมด้วยชั้นสีโปร่งแสง
พื้นหลังเบลอ
ใช้การเบลอพื้นหลังบนหน้าต่างแบบลอยเพื่อสร้างเอฟเฟกต์พื้นหลังหน้าต่างซึ่งเป็นภาพเบลอของเนื้อหาที่ซ่อนอยู่ หากต้องการเพิ่มพื้นหลังเบลอให้กับหน้าต่าง ให้ทำดังต่อไปนี้:
เรียก Window#setBackgroundBlurRadius(int) เพื่อตั้งค่ารัศมีการเบลอพื้นหลัง หรือในธีมหน้าต่าง ให้ตั้งค่า R.attr.windowBackgroundBlurRadius
ตั้งค่า R.attr.windowIsTranslucent เป็น true เพื่อทำให้หน้าต่างโปร่งแสง ภาพเบลอจะถูกวาดไว้ใต้พื้นผิวหน้าต่าง ดังนั้นหน้าต่างจะต้องโปร่งแสงเพื่อให้มองเห็นภาพเบลอได้
หรือเรียก Window#setBackgroundDrawableResource(int) เพื่อเพิ่มพื้นหลังหน้าต่างสี่เหลี่ยมที่วาดได้ด้วยสีโปร่งแสง หรือในธีมหน้าต่าง ให้ตั้งค่า R.attr.windowBackground
สำหรับหน้าต่างที่มีมุมโค้งมน ให้กำหนดมุมโค้งมนสำหรับพื้นที่เบลอโดยการตั้งค่า ShapeDrawable ที่มี มุมโค้งมน เป็นพื้นหลังของหน้าต่างที่วาดได้
จัดการสถานะเปิดใช้งานและปิดใช้งานการเบลอ โปรดดู คำแนะนำในการใช้การเบลอหน้าต่างในส่วนแอป สำหรับข้อมูลเพิ่มเติม
เบลอหลัง
ภาพเบลอด้านหลังทำให้ทั้งหน้าจอด้านหลังหน้าต่างเบลอ เอฟเฟกต์นี้ใช้เพื่อดึงความสนใจของผู้ใช้ไปยังเนื้อหาของหน้าต่างโดยการเบลอทุกสิ่งบนหน้าจอด้านหลังหน้าต่าง
หากต้องการเบลอเนื้อหาด้านหลังหน้าต่าง ให้ทำตามขั้นตอนเหล่านี้:
เพิ่ม
FLAG_BLUR_BEHIND
ลงในธงหน้าต่างเพื่อเปิดใช้งานการเบลอด้านหลัง หรือในธีมหน้าต่าง ให้ตั้งค่า R.attr.windowBlurBehindEnabledเรียก
WindowManager.LayoutParams#setBlurBehindRadius
เพื่อตั้งค่าการเบลอด้านหลังรัศมี หรือในธีมหน้าต่าง ให้ตั้งค่า R.attr.windowBlurBehindRadiusอีกทางหนึ่ง ให้เลือก ปริมาณเล็กน้อย ที่เสริมกัน
จัดการสถานะเปิดใช้งานและปิดใช้งานการเบลอ โปรดดู คำแนะนำในการใช้การเบลอหน้าต่างในส่วนแอป สำหรับข้อมูลเพิ่มเติม
แนวทางการใช้การเบลอหน้าต่างในแอพ
การรองรับ windows blur ขึ้นอยู่กับสิ่งต่อไปนี้:
เวอร์ชัน Android: Windows Blur API ใช้งานได้บน Android 12 ขึ้นไปเท่านั้น ตรวจสอบ SDK ของอุปกรณ์สำหรับเวอร์ชัน Android
ประสิทธิภาพกราฟิก: อุปกรณ์ที่มี GPU ที่มีประสิทธิภาพน้อยกว่าอาจเลือกที่จะไม่รองรับการเบลอหน้าต่าง
สถานะระบบ: เซิร์ฟเวอร์ระบบอาจปิดใช้งานการเบลอหน้าต่างชั่วคราวขณะรันไทม์ เช่น ระหว่างโหมดประหยัดแบตเตอรี่ ขณะเล่นเนื้อหาวิดีโอบางประเภท หรือเนื่องจากการแทนที่ของนักพัฒนา
เพื่อให้แอปของคุณเข้ากันได้กับเวอร์ชัน อุปกรณ์ และสถานะของระบบ Android ให้ปฏิบัติตามหลักเกณฑ์เหล่านี้:
เพิ่ม Listener ผ่าน WindowManager#addCrossWindowBlurEnabledListener เพื่อแจ้งให้คุณทราบเมื่อมีการเปิดหรือปิดใช้งานการเบลอหน้าต่าง นอกจากนี้ ให้ใช้
WindowManager#isCrossWindowBlurEnabled
เพื่อตรวจสอบว่ามีการเปิดใช้การเบลอหน้าต่างอยู่หรือไม่ใช้สองเวอร์ชันสำหรับพื้นหลังของหน้าต่าง เพื่อรองรับสถานะเปิดหรือปิดใช้งานของการเบลอหน้าต่าง
เมื่อเปิดใช้งานการเบลอ พื้นหลังของหน้าต่างควรโปร่งแสงเพื่อให้มองเห็นการเบลอได้ ในสถานะนี้ เมื่อปิดใช้งานการเบลอ เนื้อหาของหน้าต่างจะซ้อนทับกับเนื้อหาของหน้าต่างด้านล่างโดยตรง ซึ่งทำให้หน้าต่างที่ทับซ้อนกันอ่านได้น้อยลง เพื่อหลีกเลี่ยงผลกระทบดังกล่าว เมื่อปิดใช้งานการเบลอหน้าต่าง ให้ปรับ UI ของแอปดังนี้:
สำหรับการเบลอพื้นหลัง ให้เพิ่มอัลฟ่าของพื้นหลังหน้าต่างที่วาดได้ เพื่อทำให้ทึบแสงมากขึ้น
หากต้องการเบลอด้านหลัง ให้เพิ่มเลเยอร์สลัวด้วยปริมาณสลัวที่สูงขึ้น
ตัวอย่างการเบลอด้านหลังและการเบลอพื้นหลัง
ส่วนนี้จะแสดงตัวอย่างการทำงานของกิจกรรมที่ใช้ทั้งการเบลอด้านหลังและการเบลอพื้นหลัง
ตัวอย่างต่อไปนี้ของ MainActivity.java
คือกล่องโต้ตอบที่มีการเบลอด้านหลังรัศมี 20 px และรัศมีการเบลอพื้นหลัง 80 px มีมุมโค้งมน กำหนดเป็น xml ในพื้นหลังหน้าต่างที่วาดได้ มันจัดการเวอร์ชัน Android ที่แตกต่างกันอย่างถูกต้อง อุปกรณ์ต่าง ๆ (ที่อาจไม่รองรับการเบลอหน้าต่าง) และการเปิดใช้งานหรือปิดใช้งานการเปลี่ยนแปลงการเบลอรันไทม์ ช่วยให้มั่นใจว่าเนื้อหากล่องโต้ตอบสามารถอ่านได้ภายใต้เงื่อนไขใดๆ เหล่านั้น โดยการปรับอัลฟ่าที่วาดได้ของพื้นหลังหน้าต่างและจำนวนการสลัวของหน้าต่าง
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
ของ Surface Flinger ต่อไปนี้:
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
การตรวจสอบ
เพื่อตรวจสอบว่าหน้าต่างแอปของคุณมีการจัดการที่เหมาะสมเมื่อสลับระหว่างสถานะเปิดใช้งานการเบลอและปิดใช้งานการเบลอ ให้ทำตามขั้นตอนเหล่านี้:
เปิด UI ที่มีความเบลอ
เปิดหรือปิดการเบลอหน้าต่างโดย เปิดและปิดการเบลอหน้าต่าง
ตรวจสอบว่า UI ของหน้าต่างเปลี่ยนเป็นและจากสถานะเบลอตามที่คาดไว้
เปิดและปิดการเบลอหน้าต่าง
หากต้องการทดสอบว่า UI ของหน้าต่างแสดงผลด้วยเอฟเฟกต์การเบลอของหน้าต่างอย่างไร ให้เปิดหรือปิดใช้งานการเบลอโดยใช้วิธีใดวิธีหนึ่งต่อไปนี้:
จากตัวเลือกของนักพัฒนา:
การตั้งค่า -> ระบบ -> ตัวเลือกสำหรับนักพัฒนา -> การเรนเดอร์แบบเร่งด้วยฮาร์ดแวร์ -> อนุญาตการเบลอระดับหน้าต่าง
จากเทอร์มินัลบนอุปกรณ์ที่รูท:
adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them
หากต้องการตรวจสอบว่าอุปกรณ์ Android 12+ ของคุณรองรับการเบลอหน้าต่างหรือไม่ และเปิดใช้งานการเบลอหน้าต่างอยู่หรือไม่ ให้เรียกใช้ adb shell wm disable-blur
บนอุปกรณ์ที่รูท
การแก้ไขปัญหา
ใช้ข้อมูลต่อไปนี้เป็นแนวทางในการแก้ไขปัญหาระหว่างการตรวจสอบ
ไม่มีภาพเบลอ
ตรวจสอบว่าเปิดใช้งานการเบลออยู่ในปัจจุบันและฮาร์ดแวร์ของคุณรองรับ โปรดดูการ เปิดและปิดการเบลอหน้าต่าง
ตรวจสอบให้แน่ใจว่าคุณตั้งค่าสีพื้นหลังของหน้าต่างโปร่งแสง สีพื้นหลังของหน้าต่างทึบแสงจะซ่อนพื้นที่ที่เบลอ
อุปกรณ์ทดสอบไม่รองรับการเบลอหน้าต่าง
- ทดสอบแอปพลิเคชันของคุณบนโปรแกรมจำลอง Android 12 หากต้องการตั้งค่าโปรแกรมจำลอง Android โปรดดูที่ การตั้งค่าโปรแกรมจำลอง Android อุปกรณ์เสมือน Android ใด ๆ ที่คุณสร้างด้วยโปรแกรมจำลองรองรับการเบลอหน้าต่าง
ไม่มีมุมโค้งมน
- ตั้งค่าพื้นหลังหน้าต่างที่วาดได้ เพื่อกำหนดมุมโค้งมน Drawable นี้กำหนดโครงร่างของพื้นที่เบลอ
การอัปเดตตัวเลือกนักพัฒนาซอฟต์แวร์ไม่ได้เปิดใช้งานการเบลอ
- ตรวจสอบว่าอุปกรณ์อยู่ในโหมดประหยัดแบตเตอรี่หรือใช้ ช่องทางมัลติมีเดีย หรือไม่ ในอุปกรณ์ทีวีบางรุ่น การเบลอหน้าต่างอาจถูกปิดใช้งานในระหว่างการเล่นวิดีโอ
การเบลอพื้นหลังวาดแบบเต็มหน้าจอ ไม่ใช่ภายในขอบเขตหน้าต่าง
ตรวจสอบ android:windowIsFloating เพื่อให้แน่ใจว่าหน้าต่างของคุณถูกทำเครื่องหมายว่าลอยอยู่
ตรวจสอบให้แน่ใจว่าได้ตั้ง ค่าการวาดพื้นหลังของหน้าต่าง แล้ว การตั้งค่านี้จะกำหนดโครงร่างของพื้นที่เบลอ
การอัพเดตจากผู้ฟังจะไม่ถูกนำไปใช้บนหน้าจอ
- การอัปเดตตัวฟังอาจถูกนำไปใช้กับอินสแตนซ์หน้าต่างเก่า ตรวจสอบว่าหน้าต่างถูกทำลายและสร้างขึ้นใหม่ด้วยการอัปเดตตัวฟังที่ถูกต้องหรือไม่