Fenster verwischt

Mit Sammlungen den Überblick behalten Sie können Inhalte basierend auf Ihren Einstellungen speichern und kategorisieren.

In Android 12 sind öffentliche APIs zum Implementieren von Fensterunschärfeeffekten wie Hintergrundunschärfe und Unschärfe dahinter verfügbar.

Fensterunschärfen oder fensterübergreifende Unschärfen werden verwendet, um den Bildschirm hinter dem gegebenen 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 unscharfen Hintergründen erstellen, wodurch ein Milchglaseffekt entsteht.

  • Mit Blur behind können Sie den gesamten Bildschirm hinter einem (Dialog-)Fenster unkenntlich machen, wodurch ein Tiefenschärfeeffekt entsteht.

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

nur Hintergrundunschärfe

a

nur hinten verwischen

b

Unschärfe hinter und Hintergrundunschärfe

c

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

Die Fensterunschärfefunktion funktioniert fensterübergreifend, was bedeutet, dass sie auch funktioniert, 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 verwischt. 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 Unschärfe dahinter erzeugt ein Radius von 20 px einen guten Tiefenschärfeeffekt, während ein Hintergrundunschärferadius von 80 px einen guten Milchglaseffekt erzeugt. Vermeiden Sie Unschärferadien von mehr als 150 px, 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, der durch eine durchscheinende Farbschicht ergänzt wird.

Hintergrundunschärfe

Verwenden Sie Hintergrundunschärfe für schwebende Fenster, um einen Fensterhintergrundeffekt zu erstellen, der ein unscharfes Bild des darunter liegenden Inhalts ist. Gehen Sie wie folgt vor, um einen unscharfen Hintergrund für Ihr Fenster hinzuzufügen:

  1. Rufen Sie Window#setBackgroundBlurRadius(int) auf, um einen Radius für die Hintergrundunschärfe 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 bei einem Fenster mit abgerundeten Ecken die abgerundeten Ecken für den unscharfen Bereich, indem Sie ein ShapeDrawable mit abgerundeten Ecken als zeichbaren Fensterhintergrund festlegen.

  5. Behandeln Sie die aktivierten und deaktivierten Zustände für Unschärfe. Weitere Informationen finden Sie im Abschnitt Richtlinien zur Verwendung von Fensterunschärfe in Apps .

Hinten verwischen

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 verwischt wird.

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

  1. Fügen Sie FLAG_BLUR_BEHIND zu den Fensterflaggen 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 eine ergänzende Dim-Menge .

  4. Behandeln Sie die aktivierten und deaktivierten Zustände für Unschärfe. 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 für Windows Blur ist abhängig von Folgendem:

  • 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 leistungsfähigen GPUs unterstützen möglicherweise keine Fensterunschärfe.

  • Systemstatus: Der Systemserver deaktiviert möglicherweise vorübergehend die Fensterunschärfe zur Laufzeit, beispielsweise während des Batteriesparmodus, während der Wiedergabe bestimmter Arten von Videoinhalten oder aufgrund einer Überschreibung durch den Entwickler.

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

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

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

    Wenn Unschärfen aktiviert sind, sollte der Fensterhintergrund durchscheinend sein, um die Unschärfe sichtbar zu machen. Wenn Weichzeichner in diesem Zustand deaktiviert werden, ü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:

    • Erhöhen Sie für Hintergrundunschärfe das Alpha des ziehbaren Fensterhintergrunds, um ihn undurchsichtiger zu machen.

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

Beispiel für Unschärfe hinter und Hintergrundunschärfe

Dieser Abschnitt enthält ein funktionierendes Beispiel für eine Aktivität, die sowohl Hinter- als auch Hintergrundunschärfe verwendet.

Das folgende Beispiel von MainActivity.java ist ein Dialog mit einem Weichzeichnungsradius von 20 px hinter und einem Weichzeichnungsradius von 80 px für den Hintergrund. Es hat abgerundete Ecken, die im XML-Hintergrund des Fensters zeichbar sind. Es verarbeitet verschiedene Android-Versionen, verschiedene Geräte (die potenziell keine Fensterunschärfen unterstützen) und aktivierte oder deaktivierte Änderungen zur Laufzeitunschärfe korrekt. Es stellt sicher, dass der Dialoginhalt unter allen diesen Bedingungen lesbar ist, indem es das darstellbare Alpha des Fensterhintergrunds und den Dim-Wert des Fensters anpasst.

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 erzeugen, definieren wir den Fensterhintergrund in res/drawable/window_background.xml als ShapeDrawable mit abgerundeten Ecken mit Radius 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ärfe verwischt 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, setzen wir R.attr.windowIsTranslucent im Aktivitätsthema wie folgt:

<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 haben, muss der OEM erklären, dass das Gerät Fensterunschärfe unterstützt.

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

  • Stellen Sie sicher, dass das Gerät die zusätzliche GPU-Last bewältigen kann. Niedrigere Geräte sind möglicherweise nicht in der Lage, die zusätzliche Last zu bewältigen, was zu Dropped Frames führen kann. Aktivieren Sie 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 standardmäßige 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 :

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 Wechseln zwischen den Zuständen „Unschärfe aktiviert“ und „Unschärfe deaktiviert“ ordnungsgemäß 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 verschwommenen Zustand wechselt.

Fensterunschärfe ein- und ausschalten

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

  • Aus den Entwickleroptionen:

    Einstellungen -> System -> Entwickleroptionen -> Hardwarebeschleunigtes Rendern -> 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 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. Siehe Fensterunschärfe ein- und ausschalten .

  • Stellen Sie sicher, dass Sie eine durchscheinende Hintergrundfarbe für das Fenster festlegen. Eine undurchsichtige Fensterhintergrundfarbe verbirgt den verschwommenen 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 das Aktualisieren der Entwickleroption werden Unschärfen nicht aktiviert

  • Überprüfen Sie, ob sich das Gerät im Akkusparmodus befindet oder ob es Multimedia-Tunneling verwendet. Auf manchen TV-Geräten sind Fensterunschärfen möglicherweise auch während der Videowiedergabe deaktiviert.

Hintergrundunschärfe im Vollbildmodus gezeichnet, nicht innerhalb der Fenstergrenzen

  • Überprüfen Sie android:windowIsFloating , um sicherzustellen, dass Ihr Fenster als schwebend markiert ist.

  • Stellen Sie sicher, dass ein Drawable für den Fensterhintergrund festgelegt ist. Diese Einstellung bestimmt den Umriss des Unschärfebereichs.

Aktualisierungen vom Listener werden nicht auf den 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.