Desenfoques de ventana

En Android 12, las API públicas están disponibles para implementar efectos de desenfoque de ventana (como desenfoque de fondo y desenfoque detrás). Tenga en cuenta que aunque es posible que vea el desenfoque de ventana también llamado desenfoque de ventana cruzada en el código, la documentación del desarrollador o la notación de la interfaz de usuario, el desenfoque de ventana cruzada es lo mismo que el desenfoque de ventana.

Con estas API, puede difuminar lo que esté detrás de su propia ventana. Puede crear ventanas con fondos borrosos, creando un efecto de vidrio esmerilado, o mostrar ventanas con toda la pantalla detrás de ellas borrosa, creando un efecto de profundidad de campo. También puede combinar los dos efectos.

desenfoque de fondo solamente

1

desenfoque detrás solamente

2

Detrás y desenfoque de fondo

3

Figura 1. Desenfoque de fondo solamente (1), desenfoque detrás solamente (2), desenfoque de fondo y desenfoque detrás (3)

La función de desenfoque de ventana funciona en todas las ventanas, lo que significa que también funciona cuando hay otra aplicación detrás de la ventana que estás viendo. Esto no es lo mismo que un efecto de renderizado borroso , que desenfoca el contenido dentro de una ventana dentro de la misma aplicación. Los desenfoques de ventana son útiles para cuadros de diálogo y hojas inferiores, y otras ventanas flotantes.

Es importante tener en cuenta que esta característica utiliza una cantidad significativa de recursos de GPU. Entonces, aunque está disponible para todos los dispositivos Android, solo es compatible con aquellos dispositivos que tienen suficiente potencia de GPU.

Implementación

OEM y socios

Los desenfoques de ventana están desactivados de forma predeterminada. Para habilitar la funcionalidad de desenfoque en los dispositivos, haga lo siguiente:

  • Asegúrese de que el dispositivo pueda manejar la carga adicional de la GPU: la operación de desenfoque es costosa y, en los dispositivos de gama baja, puede provocar la pérdida de fotogramas. Habilite esto solo en dispositivos con suficiente potencia de GPU.
  • Asegúrese de que su librenderengine implemente la lógica de desenfoque: el motor de renderizado predeterminado de Android 12 lo hace, pero cualquier motor de renderizado personalizado debe implementar la lógica de desenfoque.
  • Habilite los desenfoques configurando el siguiente sysprop de flinger de superficie:
# enable surface flinger window blurs
PRODUCT_PROPERTY_OVERRIDES += \
       ro.surface_flinger.supports_background_blur=1

Desarrolladores de terceros

Consulte la sección Ejemplos y fuente para ver el código de ejemplo. El servidor del sistema puede deshabilitar los desenfoques de ventana en tiempo de ejecución. Por lo tanto, una aplicación debe proporcionar una versión alternativa y sin borrosidad. De lo contrario, si los desenfoques no se procesan porque estaban deshabilitados, el fondo de la ventana podría ser tan transparente que el contenido dentro de la ventana se vuelva ilegible. Si su aplicación no proporciona una versión alternativa de la aplicación, asegúrese de que su interfaz de usuario funcione tanto con los desenfoques habilitados como con los desenfoques deshabilitados. Estas son las tres condiciones bajo las cuales los desenfoques pueden desactivarse en cualquier momento:

  1. El dispositivo ejecuta Android 11 o inferior. Dado que los desenfoques de ventana solo están disponibles en dispositivos con Android 12 y versiones posteriores, las aplicaciones deben implementar una alternativa alternativa de experiencia sin imágenes borrosas para dispositivos con Android 11 y versiones anteriores.
  2. El dispositivo no admite desenfoques de ventana porque son costosos, por lo que los dispositivos de gama baja pueden perder fotogramas al renderizarlos. Para tales casos, las aplicaciones deben proporcionar una experiencia sin borrosidad alternativa.
  3. El servidor del sistema (por ejemplo, durante el modo de ahorro de batería o debido a una configuración de desarrollador o modo de túnel) desactiva el desenfoque en el tiempo de ejecución.

Los puntos 2 y 3 anteriores los informa un agente de escucha registrado con WindowManager.addCrossWindowBlurEnabledListener . Si sus aplicaciones usan las API de desenfoque, registre este agente de escucha y actualice su IU cada vez que se llame al agente de escucha, si desea usar una IU diferente para los estados de desenfoque habilitado y desenfoque deshabilitado. Cuando se registra, se llama al oyente de inmediato para informar si los desenfoques están habilitados actualmente.

Implemente las funcionalidades de desenfoque utilizando los siguientes métodos:

Ejemplos y fuente

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);
   }

Activar y desactivar el desenfoque de la ventana

Hay dos formas de permitir y prohibir el desenfoque de ventana.

  1. Desde la interfaz de usuario:

    Configuración -> Sistema -> Opciones de desarrollador -> Representación acelerada por hardware -> Permitir desenfoques a nivel de ventana

  2. Desde la terminal (el dispositivo debe estar rooteado):

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

Solo puede activar o desactivar la funcionalidad de desenfoque de ventana si su dispositivo tiene la capacidad de admitir desenfoques. (Los dispositivos que no admiten el desenfoque de ventanas no pueden habilitar la función). De manera predeterminada, los desenfoques están habilitados en los dispositivos que los admiten.

Cuando habilite los desenfoques para sus dispositivos, tenga en cuenta que otras cosas, como el modo de ahorro de batería o el túnel multimedia, pueden deshabilitarlos. Los desenfoques se habilitan cuando se cumplen todas las condiciones necesarias; son compatibles y nada los deshabilita. Para ver si el estado actual de la funcionalidad de desenfoque está "habilitado", use el comando adb shell wm disable-blur .

Validación

Para asegurarse de que su versión de las funciones de desenfoque funcione según lo previsto, implemente la lógica de la interfaz de usuario para que vuelva a dibujar los elementos de la interfaz de usuario cada vez que cambie blurEnabled (según lo informado por addCrossWindowBlurEnabledListener ).

  1. Abra la interfaz de usuario que tiene desenfoque.
  2. Utilice los pasos indicados para activar y desactivar el desenfoque de la ventana desde la interfaz de usuario o mediante la CLI.
  3. Verifique que la interfaz de usuario cambie hacia y desde una sin borrosidad como se esperaba.

Solución de problemas

Utilice lo siguiente como guía para solucionar problemas durante la validación.

Sin desenfoque dibujado

  • Verifique que los desenfoques estén actualmente habilitados (y que su hardware los admita) usando la CLI o navegando a Configuración .

    1. Utilice el comando adb shell wm disable-blur , que imprime si los desenfoques son compatibles con ese dispositivo y si están habilitados actualmente.
    2. Vaya a Configuración -> Sistema -> Opciones de desarrollador -> Representación acelerada por hardware -> Permitir desenfoques a nivel de ventana . Si no puede encontrar la opción allí, los desenfoques no son compatibles con su dispositivo.
  • Asegúrese de establecer un color de fondo de ventana translúcido; un color de fondo de ventana opaco oculta (cubre) el área borrosa.

El dispositivo de prueba no admite desenfoques de ventana

  • Pruebe su aplicación en el emulador de Android 12. Para configurar un emulador de Android, consulte las instrucciones para configurar un emulador de Android . Cualquier dispositivo virtual de Android que cree con el emulador admitirá los desenfoques de ventana.

Sin esquinas redondeadas

  • Defina las esquinas redondeadas configurando un fondo de ventana dibujable: Window#setBackgroundDrawable . Esto determina el contorno del área de desenfoque.

La actualización de la opción de desarrollador no habilita los desenfoques

  • Compruebe si el dispositivo está en modo de ahorro de batería, si está utilizando túneles multimedia (para TV) o si algo más está desactivando la función de desenfoque.

Desenfoque de fondo dibujado a pantalla completa, fuera de los límites de la ventana

  • Asegúrese de que su ventana esté marcada como flotante - android:windowIsFloating
  • Asegúrese de haber configurado un fondo de ventana dibujable: Window#setBackgroundDrawable . Esto determina el contorno del área de desenfoque.

Las actualizaciones del oyente no se aplican en la pantalla

  • Compruebe si la ventana se destruye y se vuelve a crear mientras la instancia que está operando el oyente no se actualiza. Es posible que las actualizaciones del oyente se apliquen a una instancia de ventana anterior.