窗口模糊

在 Android 中,有 12 個公共 API 可用於實現窗口模糊效果(例如背景模糊和背後模糊)。請注意,儘管您可能會在代碼、開發人員文檔或 UI 符號中看到窗口模糊,也稱為跨窗口模糊,但跨窗口模糊與窗口模糊是一回事。

使用這些 API,您可以模糊您自己的窗口後面的任何內容。您可以創建背景模糊的窗口,創建磨砂玻璃效果,或顯示窗口後面的整個屏幕都變得模糊,從而創建景深效果。您也可以將這兩種效果結合起來。

僅背景模糊

1

只在後面模糊

2

背後和背景模糊

3

圖1.背景模糊只(1),模糊僅次於(2),背景模糊和模糊後面(3)

窗口模糊功能可以跨窗口使用,這意味著當您正在查看的窗口後面有另一個應用程序時,它也可以使用。這是不一樣的一個模糊渲染效果,其模糊了相同的應用程序的窗口內的內容。窗口模糊對於對話框和底部工作表以及其他浮動窗口很有用。

請務必注意,此功能會佔用大量 GPU 資源。因此,儘管它適用於所有 Android 設備,但僅在具有足夠 GPU 能力的設備上受支持。

執行

OEM 和合作夥伴

默認情況下禁用窗口模糊。要在設備上啟用模糊功能,請執行以下操作:

  • 確保設備可以處理額外的 GPU 負載 - 模糊操作成本高昂,而且在低端設備上,可能會導致丟幀。僅在具有足夠 GPU 能力的設備上啟用此功能。
  • 確保您的librenderengine實現模糊邏輯-默認的Android 12渲染引擎的做法,但任何自定義渲染引擎必須實現模糊邏輯本身。
  • 通過設置以下表面拋油環 sysprop 啟用模糊:
# 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. 系統服務器(例如,省電模式期間,或因顯影劑設置或隧道模式)在運行時禁用模糊。

23以上均由與註冊的偵聽報導WindowManager.addCrossWindowBlurEnabledListener 。如果您的應用程序使用模糊 API,請註冊此偵聽器並在調用偵聽器時更新您的 UI,如果您想對啟用模糊和禁用模糊狀態使用不同的 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. 從用戶界面:

    設置 -> 系統 -> 開發者選項 -> 硬件加速渲染 -> 允許窗口級模糊

  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或導航設置

    1. 使用adb shell wm disable-blur命令,打印出的模糊是否支持該設備上和它們當前是否啟用。
    2. 導航到設置- >系統- >開發人員選項- >硬件加速渲染- >允許窗口級別的模糊。如果您在那裡找不到該選項,則說明您的設備不支持模糊效果。
  • 確保您設置了半透明的窗口背景顏色;不透明的窗口背景顏色隱藏(覆蓋)模糊區域。

測試設備不支持窗口模糊

  • 在 Android 12 模擬器上測試您的應用程序。要設置Android模擬器,請參閱設置Android模擬器的方向。您使用模擬器創建的任何 Android 虛擬設備都將支持窗口模糊。

沒有圓角

  • -通過設置窗口背景繪製定義圓角Window#setBackgroundDrawable 。這決定了模糊區域的輪廓。

更新開發人員選項不會啟用模糊

  • 檢查設備是否處於省電模式,是否正在使用多媒體隧道(用於電視),或者是否有其他原因禁用了模糊功能。

背景模糊全屏繪製,不在窗口範圍內

  • 確保你的窗口被標記為浮動- android:windowIsFloating
  • 確保您已設置了窗口的背景繪製- Window#setBackgroundDrawable 。這決定了模糊區域的輪廓。

來自偵聽器的更新不會應用到屏幕上

  • 檢查窗口是否被銷毀並重新創建,而偵聽器正在操作的實例未更新。偵聽器更新可能會應用於舊窗口實例。