Fenster verschwimmt

In Android 12 stehen öffentliche APIs zum Implementieren von Fensterunschärfeeffekten wie Hintergrundunschärfe und Unschärfe dahinter zur Verfügung.

Fensterunschärfen oder fensterübergreifende Unschärfen werden verwendet, um den Bildschirm hinter dem jeweiligen Fenster unscharf zu machen. Es gibt zwei Arten von Fensterunschärfen, mit denen unterschiedliche visuelle Effekte erzielt werden können:

  • Mit der Hintergrundunschärfe können Sie Fenster mit unscharfem Hintergrund erstellen und so einen Milchglaseffekt erzeugen.

  • Mit „Unschärfe hinten“ können Sie den gesamten Bildschirm hinter einem (Dialog-)Fenster unscharf machen und so einen Tiefenschärfeeffekt erzeugen.

Die beiden Effekte können separat oder kombiniert verwendet werden, wie in der folgenden Abbildung dargestellt:

Nur Hintergrundunschärfe

A

Unschärfe nur hinten

B

Unschärfe im Hintergrund und Unschärfe im Hintergrund

C

Abbildung 1. Nur Hintergrundunschärfe (a), nur Unschärfe dahinter (b), Hintergrundunschärfe und Unschärfe dahinter (c)

Die Fensterunschärfefunktion funktioniert in allen Fenstern, das heißt, sie funktioniert auch, wenn sich hinter Ihrem Fenster eine andere App befindet. Dieser Effekt ist nicht dasselbe wie der Unschärfe-Rendereffekt , der den Inhalt innerhalb desselben Fensters unscharf macht. Fensterunschärfen sind nützlich für Dialoge, untere Blätter und andere schwebende Fenster.

Implementierung

App-Entwickler

App-Entwickler müssen einen Unschärferadius angeben, um einen Unschärfeeffekt zu erzeugen. Der Unschärferadius steuert, wie dicht die Unschärfe ist, d. h. je höher der Radius, desto dichter die Unschärfe. Eine Unschärfe von 0 px bedeutet keine Unschärfe. Für die Unschärfe im Hintergrund erzeugt ein Radius von 20 Pixel einen guten Tiefenschärfeeffekt, während ein Hintergrundunschärferadius von 80 Pixel einen guten Milchglaseffekt erzeugt. Vermeiden Sie Unschärferadien über 150 Pixel, da dies die Leistung erheblich beeinträchtigt.

Um den gewünschten Unschärfeeffekt zu erzielen und die Lesbarkeit zu verbessern, wählen Sie einen Unschärferadiuswert, ergänzt durch eine durchscheinende Farbschicht.

Hintergrundunschärfe

Verwenden Sie die Hintergrundunschärfe bei schwebenden Fenstern, um einen Fensterhintergrundeffekt zu erzeugen, der ein unscharfes Bild des darunter liegenden Inhalts darstellt. Gehen Sie wie folgt vor, um einen unscharfen Hintergrund für Ihr Fenster hinzuzufügen:

  1. Rufen Sie Window#setBackgroundBlurRadius(int) auf, um einen Hintergrundunschärferadius festzulegen. Oder legen Sie im Fensterdesign R.attr.windowBackgroundBlurRadius fest.

  2. Setzen Sie R.attr.windowIsTranslucent auf true, um das Fenster durchscheinend zu machen. Die Unschärfe wird unter die Fensteroberfläche gezeichnet, daher muss das Fenster durchscheinend sein, damit die Unschärfe sichtbar ist.

  3. Rufen Sie optional Window#setBackgroundDrawableResource(int) auf, um einen rechteckigen Fensterhintergrund hinzuzufügen, der mit einer durchscheinenden Farbe gezeichnet werden kann. Oder legen Sie im Fensterdesign R.attr.windowBackground fest.

  4. Bestimmen Sie für ein Fenster mit abgerundeten Ecken die abgerundeten Ecken für den unscharfen Bereich, indem Sie ein ShapeDrawable mit abgerundeten Ecken als zeichnbaren Fensterhintergrund festlegen.

  5. Behandeln Sie die aktivierten und deaktivierten Unschärfezustände. Weitere Informationen finden Sie im Abschnitt „Richtlinien zur Verwendung von Fensterunschärfe in Apps“ .

Unschärfe dahinter

Die Unschärfe dahinter verwischt den gesamten Bildschirm hinter dem Fenster. Dieser Effekt wird verwendet, um die Aufmerksamkeit des Benutzers auf den Fensterinhalt zu lenken, indem alles auf dem Bildschirm hinter dem Fenster unscharf wird.

Gehen Sie folgendermaßen vor, um den Inhalt hinter Ihrem Fenster unkenntlich zu machen:

  1. Fügen Sie FLAG_BLUR_BEHIND zu den Fensterflags hinzu, um die Unschärfe dahinter zu aktivieren. Oder legen Sie im Fensterdesign R.attr.windowBlurBehindEnabled fest.

  2. Rufen Sie WindowManager.LayoutParams#setBlurBehindRadius auf, um eine Unschärfe hinter dem Radius festzulegen. Oder legen Sie im Fensterdesign R.attr.windowBlurBehindRadius fest.

  3. Wählen Sie optional einen ergänzenden Dimmwert .

  4. Behandeln Sie die aktivierten und deaktivierten Unschärfezustände. Weitere Informationen finden Sie im Abschnitt „Richtlinien zur Verwendung von Fensterunschärfe in Apps“ .

Richtlinien zur Verwendung von Fensterunschärfe in Apps

Die Unterstützung von Windows Blur ist von Folgendem abhängig:

  • Android-Version: Die Windows-Blur-APIs sind nur auf Android 12 und höher verfügbar. Überprüfen Sie das Geräte-SDK auf die Android-Version.

  • Grafikleistung: Geräte mit weniger leistungsstarken GPUs unterstützen möglicherweise keine Fensterunschärfe.

  • Systemstatus: Der Systemserver deaktiviert möglicherweise vorübergehend die Fensterunschärfe zur Laufzeit, z. B. im Batteriesparmodus, beim Abspielen bestimmter Arten von Videoinhalten oder aufgrund einer Entwicklerüberschreibung.

Um Ihre App mit allen Android-Versionen, Geräten und Systemzuständen kompatibel zu machen, befolgen Sie diese Richtlinien:

  • Fügen Sie über WindowManager#addCrossWindowBlurEnabledListener einen Listener hinzu, um Sie zu benachrichtigen, wenn die Fensterunschärfe aktiviert oder deaktiviert ist. Verwenden Sie außerdem WindowManager#isCrossWindowBlurEnabled um abzufragen, ob Fensterunschärfen derzeit aktiviert sind.

  • Implementieren Sie zwei Versionen für den Fensterhintergrund, um den aktivierten oder deaktivierten Status von Fensterunschärfen zu berücksichtigen.

    Wenn Unschärfen aktiviert sind, sollte der Fensterhintergrund durchscheinend sein, um die Unschärfe sichtbar zu machen. Wenn in diesem Zustand die Unschärfe deaktiviert wird, überlappt der Fensterinhalt direkt mit dem Inhalt des darunter liegenden Fensters, wodurch das überlappende Fenster weniger lesbar wird. Um einen solchen Effekt zu vermeiden, passen Sie die Benutzeroberfläche der App wie folgt an, wenn die Fensterunschärfe deaktiviert ist:

    • Um den Hintergrund unscharf zu machen, erhöhen Sie den Alphawert des zeichnbaren Fensterhintergrunds, um ihn undurchsichtiger zu machen.

    • Für eine Unschärfe im Hintergrund fügen Sie eine dunkle Ebene mit einem höheren Helligkeitsgrad hinzu.

Beispiel für Unschärfe im Hintergrund und Unschärfe im Hintergrund

In diesem Abschnitt finden Sie ein funktionierendes Beispiel für eine Aktivität, bei der sowohl Unschärfe im Hintergrund als auch Unschärfe im Hintergrund verwendet werden.

Das folgende Beispiel von MainActivity.java ist ein Dialog mit einem Unschärferadius hinter dem Hintergrund von 20 Pixel und einem Hintergrundunschärferadius von 80 Pixel. Es verfügt über abgerundete Ecken, die in XML im zeichnbaren Fensterhintergrund definiert sind. Es verarbeitet korrekt unterschiedliche Android-Versionen, unterschiedliche Geräte (die möglicherweise keine Fensterunschärfen unterstützen) und Änderungen an aktivierter oder deaktivierter Laufzeitunschärfe. Es stellt sicher, dass der Dialoginhalt unter allen diesen Bedingungen lesbar ist, indem das Zeichen-Alpha des Fensterhintergrunds und die Abdunkelung des Fensters angepasst werden.

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

Um abgerundete Ecken für das Fenster zu erstellen, definieren wir den Fensterhintergrund in res/drawable/window_background.xml als ShapeDrawable mit abgerundeten Ecken mit einem Radius von 20 dp wie folgt:

<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
    <corners android:radius="20dp"/>
    <solid android:color="#AAAAAA"/>
</shape>

Fensterunschärfen verwischen den Inhalt des Fensters unterhalb der Aktivität. Das unscharfe Bild wird unter diesem Aktivitätsfenster gezeichnet, daher muss das Aktivitätsfenster durchscheinend sein, damit die Unschärfe sichtbar ist. Um das Fenster durchscheinend zu machen, legen wir R.attr.windowIsTranslucent im Aktivitätsthema wie folgt fest:

<style name="Theme.BlurryDialog" parent="Theme.MaterialComponents.Dialog">
    <item name="android:windowIsTranslucent">true</item>
</style>

OEMs und Partner

Um Fensterunschärfe auf einem Gerät zu ermöglichen, muss der OEM erklären, dass das Gerät Fensterunschärfe unterstützt.

Um zu überprüfen, ob Ihr Gerät Fensterunschärfen unterstützt, gehen Sie wie folgt vor:

  • Stellen Sie sicher, dass das Gerät die zusätzliche GPU-Last bewältigen kann. Geräte der unteren Preisklasse sind möglicherweise nicht in der Lage, die zusätzliche Last zu bewältigen, was zu Frame-Ausfällen führen kann. Aktivieren Sie die Fensterunschärfe nur auf getesteten Geräten mit ausreichender GPU-Leistung.

  • Wenn Sie über eine benutzerdefinierte Render-Engine verfügen, stellen Sie sicher, dass Ihre Render-Engine die Unschärfelogik implementiert. Die Standard- Render-Engine von Android 12 implementiert die Unschärfelogik in BlurFilter.cpp .

Sobald Sie sichergestellt haben, dass Ihr Gerät Fensterunschärfen unterstützt, legen Sie das folgende Surface Flinger sysprop fest:

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

Validierung

Führen Sie die folgenden Schritte aus, um zu überprüfen, ob Ihr App-Fenster beim Wechsel zwischen den Zuständen „Unschärfe aktiviert“ und „Unschärfe deaktiviert“ richtig gehandhabt wird:

  1. Öffnen Sie die Benutzeroberfläche mit Unschärfe.

  2. Aktivieren oder deaktivieren Sie die Fensterunschärfe, indem Sie die Fensterunschärfe ein- und ausschalten .

  3. Stellen Sie sicher, dass die Benutzeroberfläche des Fensters wie erwartet in einen unscharfen Zustand übergeht und wieder verschwindet.

Fensterunschärfe ein- und ausschalten

Um zu testen, wie die Fenster-Benutzeroberfläche mit dem Fensterunschärfeeffekt gerendert wird, aktivieren oder deaktivieren Sie Unschärfen mit einer der folgenden Methoden:

  • Aus den Entwickleroptionen:

    Einstellungen -> System -> Entwickleroptionen -> Hardwarebeschleunigtes Rendering -> Unschärfen auf Fensterebene zulassen

  • Vom Terminal auf einem gerooteten Gerät:

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

Um zu überprüfen, ob Ihr Android 12+-Gerät Fensterunschärfen unterstützt und ob Fensterunschärfen derzeit aktiviert sind, führen Sie adb shell wm disable-blur auf einem gerooteten Gerät aus.

Fehlerbehebung

Verwenden Sie Folgendes als Leitfaden für die Fehlerbehebung während der Validierung.

Keine Unschärfe gezeichnet

  • Stellen Sie sicher, dass die Unschärfen derzeit aktiviert sind und Ihre Hardware sie unterstützt. Weitere Informationen finden Sie unter Fensterunschärfe ein- und ausschalten .

  • Stellen Sie sicher, dass Sie eine durchscheinende Hintergrundfarbe für das Fenster festlegen. Eine undurchsichtige Hintergrundfarbe des Fensters verdeckt den unscharfen Bereich.

Das Testgerät unterstützt keine Fensterunschärfe

  • Testen Sie Ihre Anwendung auf dem Android 12-Emulator. Informationen zum Einrichten eines Android-Emulators finden Sie unter Einrichten eines Android-Emulators . Jedes virtuelle Android-Gerät, das Sie mit dem Emulator erstellen, unterstützt die Fensterunschärfe.

Keine abgerundeten Ecken

Durch die Aktualisierung der Entwickleroption werden Unschärfen nicht aktiviert

  • Überprüfen Sie, ob sich das Gerät im Batteriesparmodus befindet oder Multimedia-Tunneling nutzt. Auf einigen TV-Geräten ist die Fensterunschärfe möglicherweise auch während der Videowiedergabe deaktiviert.

Hintergrundunschärfe im Vollbildmodus, nicht innerhalb der Fenstergrenzen

Aktualisierungen vom Listener werden nicht auf dem Bildschirm angewendet

  • Die Listener-Updates werden möglicherweise auf eine alte Fensterinstanz angewendet. Überprüfen Sie, ob das Fenster zerstört und mit dem richtigen Listener-Update neu erstellt wird.