In Android 12 sind öffentliche APIs für die Implementierung von Fenster-Weichzeichnereffekten wie Hintergrundweichzeichnung und Weichzeichnung hinter dem Fenster verfügbar.
Fenster-Weichzeichner oder Fensterübergreifende Weichzeichner werden verwendet, um den Bildschirm hinter dem angegebenen Fenster weichzuzeichnen. Es gibt zwei Arten von Fenster-Weichzeichnern, mit denen unterschiedliche visuelle Effekte erzielt werden können:
Mit der Hintergrundweichzeichnung können Sie Fenster mit weichgezeichneten Hintergründen erstellen, wodurch ein Milchglaseffekt entsteht.
Mit der Weichzeichnung hinter dem Fenster können Sie den gesamten Bildschirm hinter einem (Dialog-)Fenster weichzeichnen, wodurch ein Tiefenschärfeeffekt entsteht.
Die beiden Effekte können separat oder kombiniert verwendet werden, wie in der folgenden Abbildung dargestellt:
a |
b |
![]() c |
Abbildung 1 : Nur Hintergrundweichzeichnung (a), nur Weichzeichnung hinter dem Fenster (b), Hintergrundweichzeichnung und Weichzeichnung hinter dem Fenster (c)
Die Funktion „Fenster-Weichzeichnung“ funktioniert fensterübergreifend, d. h. sie funktioniert auch, wenn sich hinter Ihrem Fenster eine andere App befindet. Dieser Effekt ist nicht mit dem Weichzeichnungseffekt identisch, der den Inhalt innerhalb desselben Fensters weichzeichnet. Fenster-Weichzeichner sind nützlich für Dialogfelder, Ansichten am unteren Rand und andere unverankerte Fenster.
Implementierung
App-Entwickler
App-Entwickler müssen einen Weichzeichnungsradius angeben, um einen Weichzeichnungseffekt zu erstellen. Mit dem Weichzeichnungsradius wird die Dichte der Weichzeichnung gesteuert. Je höher der Radius, desto dichter die Weichzeichnung. Eine Weichzeichnung von 0 Pixel bedeutet keine Weichzeichnung. Bei der Weichzeichnung hinter dem Fenster erzeugt ein Radius von 20 Pixel einen guten Tiefenschärfeeffekt, während ein Hintergrundweichzeichnungsradius von 80 Pixel einen guten Milchglaseffekt erzeugt. Vermeiden Sie Weichzeichnungsradien über 150 Pixel, da dies die Leistung erheblich beeinträchtigt.
Um den gewünschten Weichzeichnungseffekt zu erzielen und die Lesbarkeit zu erhöhen, wählen Sie einen Weichzeichnungsradiuswert aus, der durch eine durchscheinende Farbschicht ergänzt wird.
Hintergrundweichzeichnung
Verwenden Sie die Hintergrundweichzeichnung in unverankerten Fenstern, um einen Fensterhintergrundeffekt zu erstellen, der ein weichgezeichnetes Bild des zugrunde liegenden Inhalts ist. So fügen Sie Ihrem Fenster einen weichgezeichneten Hintergrund hinzu:
Rufen Sie Window#setBackgroundBlurRadius(int) auf, um einen Hintergrundweichzeichnungsradius festzulegen. Alternativ können Sie im Fensterdesign R.attr.windowBackgroundBlurRadius festlegen.
Setzen Sie R.attr.windowIsTranslucent auf „true“, um das Fenster durchscheinend zu machen. Die Weichzeichnung wird unter der Fensterfläche gezeichnet. Daher muss das Fenster durchscheinend sein, damit die Weichzeichnung sichtbar ist.
Optional können Sie Window#setBackgroundDrawableResource(int) aufrufen, um ein rechteckiges Fensterhintergrund-Drawable mit einer durchscheinenden Farbe hinzuzufügen. Alternativ können Sie im Fensterdesign R.attr.windowBackground festlegen.
Bei einem Fenster mit abgerundeten Ecken legen Sie die abgerundeten Ecken für den weichgezeichneten Bereich fest, indem Sie ein ShapeDrawable mit abgerundeten Ecken als Fensterhintergrund-Drawable festlegen.
Verarbeiten Sie die Zustände „Weichzeichnung aktiviert“ und „Weichzeichnung deaktiviert“. Weitere Informationen finden Sie im Abschnitt Richtlinien zur Verwendung von Fenster-Weichzeichnern in Apps.
Weichzeichnung hinter dem Fenster
Bei der Weichzeichnung hinter dem Fenster wird der gesamte Bildschirm hinter dem Fenster weichgezeichnet. Dieser Effekt wird verwendet, um die Aufmerksamkeit des Nutzers auf den Fensterinhalt zu lenken, indem alles auf dem Bildschirm hinter dem Fenster weichgezeichnet wird.
So weichzeichnen Sie den Inhalt hinter Ihrem Fenster:
Fügen Sie
FLAG_BLUR_BEHINDden Fenster-Flags hinzu, um die Weichzeichnung hinter dem Fenster zu aktivieren. Alternativ können Sie im Fensterdesign R.attr.windowBlurBehindEnabled festlegen.Rufen Sie
WindowManager.LayoutParams#setBlurBehindRadiusauf, um einen Radius für die Weichzeichnung hinter dem Fenster festzulegen. Alternativ können Sie im Fensterdesign R.attr.windowBlurBehindRadius festlegen.Optional können Sie einen ergänzenden Abdunklungsbetrag auswählen.
Verarbeiten Sie die Zustände „Weichzeichnung aktiviert“ und „Weichzeichnung deaktiviert“. Weitere Informationen finden Sie im Abschnitt Richtlinien zur Verwendung von Fenster-Weichzeichnern in Apps.
Richtlinien zur Verwendung von Fenster-Weichzeichnern in Apps
Die Unterstützung für Fenster-Weichzeichner hängt von Folgendem ab:
Android-Version: Die APIs für Fenster-Weichzeichner sind nur in Android 12 und höher verfügbar. Prüfen Sie das Geräte-SDK auf die Android-Version.
Grafikleistung: Auf Geräten mit weniger leistungsstarken GPUs werden Fenster-Weichzeichner möglicherweise nicht unterstützt.
Systemstatus: Der Systemserver kann Fenster-Weichzeichner zur Laufzeit vorübergehend deaktivieren, z. B. im Energiesparmodus, bei der Wiedergabe bestimmter Arten von Videoinhalten oder aufgrund einer Entwicklerüberschreibung.
Damit Ihre App mit verschiedenen Android-Versionen, Geräten und Systemstatus kompatibel ist, folgen Sie diesen Richtlinien:
Fügen Sie über WindowManager#addCrossWindowBlurEnabledListener einen Listener hinzu, um benachrichtigt zu werden, wenn die Fenster-Weichzeichner aktiviert oder deaktiviert werden. Verwenden Sie außerdem
WindowManager#isCrossWindowBlurEnabled, um abzufragen ob Fenster-Weichzeichner derzeit aktiviert sind.Implementieren Sie zwei Versionen für den Fensterhintergrund, um den aktivierten oder deaktivierten Zustand von Fenster-Weichzeichnern zu berücksichtigen.
Wenn Weichzeichner aktiviert sind, muss der Fensterhintergrund durchscheinend sein, damit die Weichzeichnung sichtbar ist. Wenn in diesem Zustand die Weichzeichner deaktiviert werden, überlappt der Fensterinhalt direkt mit dem Inhalt des zugrunde liegenden Fensters, wodurch das überlappende Fenster weniger gut lesbar ist. Um diesen Effekt zu vermeiden, passen Sie die Benutzeroberfläche der App wie folgt an, wenn Fenster-Weichzeichner deaktiviert sind:
Erhöhen Sie bei der Hintergrundweichzeichnung den Alphawert des Fensterhintergrund-Drawables, damit es undurchsichtiger wird.
Fügen Sie bei der Weichzeichnung hinter dem Fenster eine Abdunklungsebene mit einem höheren Abdunklungsbetrag hinzu.
Beispiel für Weichzeichnung hinter dem Fenster und Hintergrundweichzeichnung
In diesem Abschnitt finden Sie ein funktionierendes Beispiel für eine Aktivität, bei der sowohl die Weichzeichnung hinter dem Fenster als auch die Hintergrundweichzeichnung verwendet wird.
Im folgenden Beispiel für MainActivity.java wird ein Dialogfeld mit einem Radius von 20 Pixel für die Weichzeichnung hinter dem Fenster und einem Radius von 80 Pixel für die Hintergrundweichzeichnung verwendet. Es hat abgerundete Ecken, die in XML im Fensterhintergrund-Drawable definiert sind. Es verarbeitet verschiedene Android-Versionen, verschiedene Geräte (die möglicherweise keine Fenster-Weichzeichner unterstützen) und Änderungen an der Aktivierung oder Deaktivierung der Weichzeichnung zur Laufzeit korrekt. Es sorgt dafür, dass der Dialogfeldinhalt unter allen diesen Bedingungen lesbar ist, indem der Alphawert des Fensterhintergrund-Drawables und der Abdunklungsbetrag 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:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="20dp"/>
<solid android:color="#AAAAAA"/>
</shape>
Fenster-Weichzeichner weichzeichnen den Inhalt des Fensters unterhalb der Aktivität. Das weichgezeichnete Bild wird unter diesem Aktivitätsfenster gezeichnet. Daher muss das Aktivitätsfenster durchscheinend sein, damit die Weichzeichnung sichtbar ist. Um das Fenster durchscheinend zu machen, legen wir R.attr.windowIsTranslucent in dem Aktivitätsdesign wie folgt fest:
<style name="Theme.BlurryDialog" parent="Theme.MaterialComponents.Dialog">
<item name="android:windowIsTranslucent">true</item>
</style>
OEMs und Partner
Damit die Fenster-Weichzeichnung auf einem Gerät funktioniert, muss der OEM deklarieren, dass das Gerät Fenster-Weichzeichner unterstützt.
So prüfen Sie, ob Ihr Gerät Fenster-Weichzeichner unterstützt:
Achten Sie darauf, dass das Gerät die zusätzliche GPU-Last bewältigen kann. Auf Geräten der unteren Preisklasse kann die zusätzliche Last möglicherweise nicht bewältigt werden, was zu Frame-Verlusten führen kann. Aktivieren Sie Fenster-Weichzeichner nur auf getesteten Geräten mit ausreichender GPU-Leistung.
Wenn Sie eine benutzerdefinierte Rendering-Engine verwenden, achten Sie darauf, dass die Rendering-Engine die Weichzeichnungslogik implementiert. Die Standard-Rendering-Engine von Android 12 implementiert die Weichzeichnungslogik in
BlurFilter.cpp.
Sobald Sie sicher sind, dass Ihr Gerät Fenster-Weichzeichner unterstützt, legen Sie die folgende SurfaceFlinger-sysprop fest:
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
Validierung
So prüfen Sie, ob Ihr App-Fenster beim Wechsel zwischen den Zuständen „Weichzeichnung aktiviert“ und „Weichzeichnung deaktiviert“ ordnungsgemäß verarbeitet wird:
Öffnen Sie die Benutzeroberfläche mit der Weichzeichnung.
Aktivieren oder deaktivieren Sie Fenster-Weichzeichner, indem Sie die Fenster-Weichzeichnung ein- und ausschalten.
Prüfen Sie, ob sich die Fenster-Benutzeroberfläche wie erwartet in einen weichgezeichneten Zustand ändert und wieder zurückkehrt.
Fenster-Weichzeichnung ein- und ausschalten
Wenn Sie testen möchten, wie die Fenster-Benutzeroberfläche mit dem Effekt „Fenster-Weichzeichnung“ gerendert wird, aktivieren oder deaktivieren Sie die Weichzeichnung mit einer der folgenden Methoden:
Über die Entwickleroptionen:
Einstellungen -> System -> Entwickleroptionen -> Hardwarebeschleunigtes Rendering -> Weichzeichnung auf Fensterebene zulassen
Über das Terminal auf einem gerooteten Gerät:
adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them
Wenn Sie prüfen möchten, ob Ihr Android 12-Gerät oder höher Fenster-Weichzeichner unterstützt und ob Fenster-Weichzeichner derzeit aktiviert sind, führen Sie auf einem gerooteten Gerät adb shell wm disable-blur aus.
Fehlerbehebung
Verwenden Sie die folgenden Informationen als Leitfaden für die Fehlerbehebung während der Validierung.
Keine Weichzeichnung
Prüfen Sie, ob die Weichzeichnung derzeit aktiviert ist und ob Ihre Hardware sie unterstützt. Weitere Informationen finden Sie unter Fenster-Weichzeichnung ein- und ausschalten.
Achten Sie darauf, dass Sie eine durchscheinende Fensterhintergrundfarbe festlegen. Bei einer undurchsichtigen Fensterhintergrundfarbe wird der weichgezeichnete Bereich ausgeblendet.
Das Testgerät unterstützt keine Fenster-Weichzeichner
- Testen Sie Ihre Anwendung im Android 12-Emulator. Informationen zum Einrichten eines Android-Emulators finden Sie unter Android-Emulator einrichten. Jedes virtuelle Android-Gerät, das Sie mit dem Emulator erstellen, unterstützt die Fenster-Weichzeichner.
Keine abgerundeten Ecken
- Legen Sie ein Fensterhintergrund-Drawable fest um abgerundete Ecken zu definieren. Dieses Drawable bestimmt den Umriss des weichgezeichneten Bereichs.
Durch das Aktualisieren der Entwickleroption werden keine Weichzeichner aktiviert
- Prüfen Sie, ob sich das Gerät im Energiesparmodus befindet oder ob Multimedia-Tunneling verwendet wird. Auf einigen TV-Geräten werden Fenster-Weichzeichner möglicherweise auch während der Videowiedergabe deaktiviert.
Hintergrundweichzeichnung wird im Vollbildmodus und nicht innerhalb der Fenstergrenzen gezeichnet
Prüfen Sie, ob android:windowIsFloating festgelegt ist, damit Ihr Fenster als unverankert markiert ist.
Achten Sie darauf, dass ein Fensterhintergrund-Drawable festgelegt ist. Mit dieser Einstellung wird der Umriss des Weichzeichnungsbereichs festgelegt.
Updates vom Listener werden nicht auf dem Bildschirm angewendet
- Die Listener-Updates werden möglicherweise auf eine alte Fensterinstanz angewendet. Prüfen Sie, ob das Fenster zerstört und mit dem richtigen Listener-Update neu erstellt wird.
