ใน Android 12 มี API สาธารณะให้ใช้ เพื่อใช้เอฟเฟกต์เบลอหน้าต่าง เช่น เบลอพื้นหลังและเบลอข้างหลัง
การเบลอหน้าต่างหรือการเบลอข้ามหน้าต่างใช้เพื่อเบลอหน้าจอที่อยู่ด้านหลังหน้าต่างที่ระบุ การเบลอหน้าต่างมี 2 ประเภท ซึ่งใช้เพื่อสร้างเอฟเฟกต์ภาพที่แตกต่างกันได้
การเบลอพื้นหลังช่วยให้คุณสร้างหน้าต่างที่มีพื้นหลังเบลอ สร้างเอฟเฟกต์กระจกฝ้า
เบลอพื้นหลังช่วยให้คุณเบลอทั้งหน้าจอที่อยู่ด้านหลังหน้าต่าง (กล่องโต้ตอบ) เพื่อสร้างเอฟเฟกต์ระยะชัดลึก
คุณใช้เอฟเฟกต์ทั้ง 2 อย่างแยกกันหรือใช้ร่วมกันก็ได้ ดังที่แสดงในรูปต่อไปนี้
![]() a |
![]() b |
![]() ค |
รูปที่ 1 เบลอพื้นหลังเท่านั้น (ก), เบลอเฉพาะด้านหลัง (ข), เบลอพื้นหลังและเบลอเฉพาะด้านหลัง (ค)
ฟีเจอร์เบลอหน้าต่างจะทำงานในหน้าต่างต่างๆ ซึ่งหมายความว่าจะทำงานได้แม้ว่าจะมีแอปอื่นอยู่เบื้องหลังหน้าต่างของคุณ เอฟเฟกต์นี้ไม่เหมือนกับเอฟเฟกต์การแสดงผลแบบเบลอ ซึ่งจะเบลอเนื้อหาภายในหน้าต่างเดียวกัน การเบลอหน้าต่างมีประโยชน์สำหรับกล่องโต้ตอบ Bottom Sheet และหน้าต่างลอยอื่นๆ
การใช้งาน
นักพัฒนาแอป
นักพัฒนาแอปต้องระบุรัศมีการเบลอเพื่อสร้างเอฟเฟกต์เบลอ รัศมีการเบลอจะควบคุมความหนาแน่นของการเบลอ กล่าวคือ ยิ่งรัศมีสูง การเบลอก็จะยิ่งหนาแน่น ค่าเบลอ 0 พิกเซลหมายถึงไม่มีการเบลอ สำหรับเบลอพื้นหลัง รัศมี 20 พิกเซลจะสร้างเอฟเฟกต์ระยะชัดลึกที่ดี ส่วนรัศมีเบลอพื้นหลัง 80 พิกเซลจะสร้างเอฟเฟกต์กระจกฝ้าที่ดี หลีกเลี่ยงรัศมีการเบลอที่สูงกว่า 150 พิกเซล เนื่องจากจะส่งผลต่อประสิทธิภาพอย่างมาก
หากต้องการให้ได้เอฟเฟกต์เบลอตามที่ต้องการและเพิ่มความสามารถในการอ่าน ให้เลือกค่ารัศมี เบลอที่เสริมด้วยเลเยอร์สีโปร่งแสง
การเบลอพื้นหลัง
ใช้การเบลอพื้นหลังในหน้าต่างลอยเพื่อสร้างเอฟเฟกต์พื้นหลังของหน้าต่าง ซึ่งเป็นรูปภาพที่เบลอของเนื้อหาที่อยู่เบื้องหลัง หากต้องการเพิ่มพื้นหลังเบลอให้กับหน้าต่าง ให้ทำดังนี้
เรียกใช้ Window#setBackgroundBlurRadius(int) เพื่อ ตั้งค่ารัศมีการเบลอพื้นหลัง หรือตั้งค่า R.attr.windowBackgroundBlurRadius ในธีมหน้าต่าง
ตั้งค่า R.attr.windowIsTranslucent เป็น true เพื่อให้หน้าต่างโปร่งแสง ระบบจะวาดภาพเบลอใต้พื้นผิวหน้าต่าง ดังนั้นหน้าต่างจึงต้องโปร่งแสงเพื่อให้มองเห็นภาพเบลอ
ไม่บังคับ ให้เรียกใช้ Window#setBackgroundDrawableResource(int) เพื่อ เพิ่ม Drawable พื้นหลังหน้าต่างสี่เหลี่ยมที่มีสีโปร่งแสง หรือตั้งค่า R.attr.windowBackground ในธีมหน้าต่าง
สำหรับหน้าต่างที่มีมุมโค้ง ให้กำหนดมุมโค้งสำหรับ พื้นที่เบลอโดยตั้งค่า ShapeDrawable ที่มีมุมโค้ง เป็น Drawable พื้นหลังของหน้าต่าง
จัดการสถานะเปิดและปิดใช้การเบลอแฮนเดิล ดูข้อมูลเพิ่มเติมได้ที่ส่วนหลักเกณฑ์การใช้การเบลอหน้าต่างในแอป
เบลอพื้นหลัง
การเบลอที่อยู่ด้านหลังจะเบลอทั้งหน้าจอที่อยู่ด้านหลังหน้าต่าง เอฟเฟกต์นี้ใช้เพื่อ ดึงดูดความสนใจของผู้ใช้ไปยังเนื้อหาในหน้าต่างโดยการเบลอทุกอย่าง บนหน้าจอที่อยู่ด้านหลังหน้าต่าง
หากต้องการเบลอเนื้อหาด้านหลังหน้าต่าง ให้ทำตามขั้นตอนต่อไปนี้
เพิ่ม
FLAG_BLUR_BEHIND
ลงในแฟล็กของหน้าต่างเพื่อเปิดใช้การเบลอพื้นหลัง หรือตั้งค่า R.attr.windowBlurBehindEnabled ในธีมหน้าต่างเรียกใช้
WindowManager.LayoutParams#setBlurBehindRadius
เพื่อ ตั้งค่ารัศมีการเบลอพื้นหลัง หรือตั้งค่า R.attr.windowBlurBehindRadius ในธีมหน้าต่างเลือกจำนวนหรี่ที่เสริมกัน (ไม่บังคับ)
จัดการสถานะเปิดและปิดใช้การเบลอแฮนเดิล ดูข้อมูลเพิ่มเติมได้ที่ส่วนหลักเกณฑ์การใช้การเบลอหน้าต่างในแอป
หลักเกณฑ์ในการใช้การเบลอหน้าต่างในแอป
การรองรับการเบลอหน้าต่างขึ้นอยู่กับสิ่งต่อไปนี้
เวอร์ชัน Android: API การเบลอหน้าต่างใช้ได้ใน Android 12 ขึ้นไปเท่านั้น ตรวจสอบ SDK ของอุปกรณ์สำหรับเวอร์ชัน Android
ประสิทธิภาพกราฟิก: อุปกรณ์ที่มี GPU ประสิทธิภาพต่ำอาจเลือกไม่รองรับการเบลอหน้าต่าง
สถานะระบบ: เซิร์ฟเวอร์ระบบอาจปิดเบลอหน้าต่างชั่วคราวใน รันไทม์ เช่น ในโหมดประหยัดแบตเตอรี ขณะเล่นวิดีโอ บางประเภท หรือเนื่องจากการลบล้างของนักพัฒนาแอป
หากต้องการให้แอปของคุณใช้งานได้กับ Android เวอร์ชัน อุปกรณ์ และสถานะระบบต่างๆ ให้ทำตามหลักเกณฑ์ต่อไปนี้
เพิ่ม Listener ผ่าน WindowManager#addCrossWindowBlurEnabledListener เพื่อแจ้งให้คุณทราบเมื่อมีการเปิดหรือปิดใช้การเบลอหน้าต่าง นอกจากนี้ ให้ใช้
WindowManager#isCrossWindowBlurEnabled
เพื่อค้นหาว่ามีการเปิดใช้การเบลอหน้าต่างอยู่หรือไม่ใช้พื้นหลังหน้าต่าง 2 เวอร์ชันเพื่อให้รองรับสถานะเปิดหรือปิดใช้การเบลอหน้าต่าง
เมื่อเปิดใช้การเบลอ พื้นหลังของหน้าต่างควรโปร่งแสงเพื่อให้มองเห็นการเบลอ ในสถานะนี้ เมื่อปิดใช้การเบลอ เนื้อหาของหน้าต่างจะ ซ้อนทับกับเนื้อหาของหน้าต่างด้านล่างโดยตรง ทำให้ หน้าต่างที่ซ้อนทับอ่านยากขึ้น หากต้องการหลีกเลี่ยงผลกระทบดังกล่าว เมื่อปิดใช้การเบลอหน้าต่าง ให้ปรับ UI ของแอปดังนี้
สําหรับการเบลอพื้นหลัง ให้เพิ่มค่าอัลฟ่าของพื้นหลังหน้าต่าง drawable เพื่อให้ทึบแสงมากขึ้น
หากต้องการเบลอพื้นหลัง ให้เพิ่มเลเยอร์หรี่แสงที่มีค่าการหรี่แสงสูงขึ้น
ตัวอย่างการเบลอพื้นหลังและเบลอพื้นหลัง
ส่วนนี้แสดงตัวอย่างการทำงานของกิจกรรมที่ใช้ทั้ง blur behind และการเบลอพื้นหลัง
ตัวอย่างต่อไปนี้ของ MainActivity.java
คือกล่องโต้ตอบที่มีรัศมีการเบลอ
ด้านหลัง 20 พิกเซลและรัศมีการเบลอพื้นหลัง 80 พิกเซล โดยมี
มุมโค้งมนที่กำหนดไว้ใน XML ใน Drawable ของพื้นหลังหน้าต่าง โดยจะจัดการเวอร์ชัน Android ต่างๆ อุปกรณ์ต่างๆ (ที่อาจไม่รองรับการเบลอหน้าต่าง) และการเปลี่ยนแปลงที่เปิดหรือปิดใช้การเบลอรันไทม์ได้อย่างถูกต้อง ซึ่งจะช่วยให้เนื้อหาในกล่องโต้ตอบอ่านได้ในทุกกรณีโดยการปรับค่าอัลฟ่าของ Drawable พื้นหลังของหน้าต่างและปริมาณการหรี่แสงของหน้าต่าง
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
เมื่อตรวจสอบแล้วว่าอุปกรณ์รองรับการเบลอหน้าต่าง ให้ตั้งค่า
surface flinger sysprop
ดังนี้
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 พื้นหลังของหน้าต่าง เพื่อกำหนดมุมโค้ง Drawable นี้จะกำหนดเส้นขอบของพื้นที่เบลอ
การอัปเดตตัวเลือกสำหรับนักพัฒนาแอปไม่ได้เปิดใช้การเบลอ
- ตรวจสอบว่าอุปกรณ์อยู่ในโหมดประหยัดแบตเตอรี่หรือใช้การเชื่อมต่อมัลติมีเดียหรือไม่ นอกจากนี้ ในอุปกรณ์ทีวีบางรุ่น ระบบอาจปิดใช้การเบลอหน้าต่างระหว่างการเล่นวิดีโอด้วย
การเบลอพื้นหลังที่วาดเต็มหน้าจอ ไม่ใช่ภายในขอบเขตของหน้าต่าง
ตรวจสอบ android:windowIsFloating เพื่อให้แน่ใจว่ามีการทำเครื่องหมายหน้าต่างเป็นแบบลอย
ตรวจสอบว่าได้ตั้งค่า drawable พื้นหลังของหน้าต่างแล้ว การตั้งค่านี้จะกำหนด เส้นขอบของพื้นที่เบลอ
การอัปเดตจาก Listener จะไม่แสดงบนหน้าจอ
- การอัปเดต Listener อาจมีผลกับอินสแตนซ์หน้าต่างเก่า ตรวจสอบว่าหน้าต่างถูกทำลายและสร้างใหม่ด้วยการอัปเดต Listener ที่ถูกต้องหรือไม่