Размытие окна

В Android 12 доступны общедоступные API-интерфейсы для реализации эффектов размытия окна (например, размытие фона и размытие позади). Обратите внимание, что хотя в коде, документации для разработчиков или нотации пользовательского интерфейса вы можете увидеть размытие окон, также называемое размытием поперек окна, размытие поперек окна — это то же самое, что и размытие окна.

С помощью этих API вы можете размыть все, что находится за вашим окном. Вы можете создавать окна с размытым фоном, создавая эффект матового стекла, или отображать окна с размытием всего экрана за ними, создавая эффект глубины резкости. Вы также можете комбинировать два эффекта.

только размытие фона

1

размытие только сзади

2

сзади и размытие фона

3

Рис. 1. Размытие только фона (1), размытие только сзади (2), размытие фона и размытие сзади (3)

Функция размытия окна работает во всех окнах, что означает, что она также работает, когда за окном, которое вы просматриваете, есть другое приложение. Это не то же самое, что эффект рендеринга размытия , который размывает содержимое внутри окна в том же приложении. Размытие окон полезно для диалогов, нижних листов и других плавающих окон.

Важно отметить, что эта функция использует значительные ресурсы графического процессора. Поэтому, хотя он доступен для всех устройств Android, он поддерживается только на тех устройствах, которые имеют достаточную мощность графического процессора.

Реализация

OEM-производители и партнеры

Размытие окон по умолчанию отключено. Чтобы включить функцию размытия на устройствах, сделайте следующее:

  • Убедитесь, что устройство может справиться с дополнительной нагрузкой на графический процессор — операция размытия требует больших затрат, а на слабых устройствах она может привести к пропуску кадров. Включайте это только на устройствах с достаточной мощностью графического процессора.
  • Убедитесь, что ваш librenderengine реализует логику размытия — механизм рендеринга Android 12 по умолчанию делает это, но любой пользовательский механизм рендеринга должен сам реализовывать логику размытия.
  • Включите размытие, установив следующую системную команду для отображения поверхности:
# enable surface flinger window blurs
PRODUCT_PROPERTY_OVERRIDES += \
       ro.surface_flinger.supports_background_blur=1

Сторонние разработчики

Обратитесь к разделу « Примеры и исходный код », чтобы увидеть пример кода. Размытие окна может быть отключено системным сервером во время выполнения. Поэтому приложение должно предоставлять резервную версию без размытия. В противном случае, если размытие не визуализируется из-за того, что оно было отключено, фон окна может быть настолько прозрачным, что содержимое внутри окна станет неразборчивым. Если ваше приложение не предоставляет резервную версию приложения, убедитесь, что ваш пользовательский интерфейс работает как с включенным, так и с отключенным размытием. Это три условия, при которых размытие можно отключить в любое время:

  1. Устройство работает под управлением Android 11 или более ранней версии. Поскольку размытие окон доступно только на устройствах Android 12 и более поздних версий, приложения должны реализовывать резервную альтернативу без размытия для устройств под управлением Android 11 и более ранних версий.
  2. Устройство не поддерживает размытие окна, потому что оно дорогое, поэтому устройства более низкого уровня могут пропускать кадры при их рендеринге. В таких случаях приложения должны обеспечивать резервный режим без размытия.
  3. Системный сервер (например, в режиме энергосбережения, в настройках разработчика или в туннельном режиме) отключает размытие во время выполнения.

О пунктах 2 и 3 выше сообщает прослушиватель, зарегистрированный с помощью WindowManager.addCrossWindowBlurEnabledListener . Если ваши приложения используют API-интерфейсы размытия, зарегистрируйте этот прослушиватель и обновляйте свой пользовательский интерфейс всякий раз, когда вызывается прослушиватель, если вы хотите использовать другой пользовательский интерфейс для состояний с включенным и отключенным размытием. Когда он зарегистрирован, прослушиватель немедленно вызывается, чтобы сообщить, включено ли в настоящее время размытие.

Реализуйте функции размытия, используя следующие методы:

Примеры и источник

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 .

Проверка

Чтобы ваша версия функций размытия работала так, как вы предполагали, реализуйте логику пользовательского интерфейса, чтобы она перерисовывала элементы пользовательского интерфейса всякий раз, когда изменяется blurEnabled (как сообщает addCrossWindowBlurEnabledListener ).

  1. Откройте пользовательский интерфейс с размытием.
  2. Используйте шаги, указанные для включения и выключения размытия окна с помощью пользовательского интерфейса или интерфейса командной строки.
  3. Убедитесь, что пользовательский интерфейс меняется на размытый и обратно, как и ожидалось.

Поиск проблемы

Используйте следующее в качестве руководства по устранению неполадок во время проверки.

Размытие не нарисовано

  • Убедитесь, что размытие в настоящее время включено (и поддерживает ли ваше оборудование) либо с помощью интерфейса командной строки, либо перейдя в « Настройки ».

    1. Используйте команду adb shell wm disable-blur , которая выводит информацию о том, поддерживаются ли размытия на этом устройстве и включены ли они в данный момент.
    2. Перейдите в « Настройки» -> «Система» -> «Параметры разработчика» -> «Аппаратное ускорение рендеринга» -> «Разрешить размытие на уровне окна» . Если вы не можете найти эту опцию, размытие не поддерживается на вашем устройстве.
  • Убедитесь, что вы установили полупрозрачный цвет фона окна; непрозрачный цвет фона окна скрывает (покрывает) размытую область.

Тестовое устройство не поддерживает размытие окна

  • Протестируйте свое приложение на эмуляторе Android 12. Чтобы настроить эмулятор Android, см. инструкции по настройке эмулятора Android . Любое виртуальное устройство Android, которое вы создадите с помощью эмулятора, будет поддерживать размытие окна.

Нет закругленных углов

  • Определите закругленные углы, установив рисуемый фон окна — Window#setBackgroundDrawable . Это определяет контур области размытия.

Обновление параметра разработчика не включает размытие

  • Проверьте, находится ли устройство в режиме экономии заряда батареи, использует ли оно мультимедийное туннелирование (для ТВ) или что-то еще отключает функцию размытия.

Размытие фона нарисовано в полноэкранном режиме, а не в границах окна

  • Убедитесь, что ваше окно помечено как плавающее — android:windowIsFloating
  • Убедитесь, что вы установили фон окна для рисования - Window#setBackgroundDrawable . Это определяет контур области размытия.

Обновления от слушателя не применяются на экране

  • Проверьте, уничтожается ли окно и воссоздается ли оно, в то время как экземпляр, над которым работает слушатель, не обновляется. Обновления прослушивателя могут применяться к старому экземпляру окна.