W Androidzie 12 dostępne są publiczne interfejsy API do implementowania efektów rozmycia okna, takich jak rozmycie tła i rozmycie za.
Rozmycia okna, czyli rozmycia między oknami, służą do rozmywania ekranu za danym oknem. Istnieją 2 rodzaje rozmycia okna, których można używać do uzyskiwania różnych efektów wizualnych:
Rozmycie tła umożliwia tworzenie okien z rozmytym tłem, co daje efekt matowego szkła.
Rozmycie za umożliwia rozmycie całego ekranu za oknem (dialogowym), co daje efekt głębi ostrości.
Te 2 efekty można stosować oddzielnie lub łącznie, jak pokazano na ilustracji poniżej:
a |
b |
![]() c |
Rysunek 1. Tylko rozmycie tła (a), tylko rozmycie za (b), rozmycie tła i rozmycie za (c)
Funkcja rozmycia okna działa w różnych oknach, co oznacza, że działa też, gdy za Twoim oknem znajduje się inna aplikacja. Ten efekt nie jest taki sam jak efekt rozmycia renderowania, który rozmywa treści wewnątrz tego samego okna. Rozmycia okna są przydatne w przypadku okien dialogowych, plansz dolnych i innych okien pływających.
Implementacja
Programiści aplikacji
Aby utworzyć efekt rozmycia, programiści aplikacji muszą podać promień rozmycia. Promień rozmycia określa, jak gęste jest rozmycie. Im większy promień, tym gęstsze rozmycie. Rozmycie o promieniu 0 pikseli oznacza brak rozmycia. W przypadku rozmycia za promień 20 pikseli daje dobry efekt głębi ostrości, a promień rozmycia tła 80 pikseli daje dobry efekt matowego szkła. Unikaj promieni rozmycia większych niż 150 pikseli, ponieważ może to znacznie wpłynąć na wydajność.
Aby uzyskać pożądany efekt rozmycia i zwiększyć czytelność, wybierz wartość promienia rozmycia uzupełnioną o półprzezroczystą warstwę koloru.
Rozmycie tła
Użyj rozmycia tła w oknach pływających, aby utworzyć efekt tła okna, który jest rozmytym obrazem treści znajdujących się pod nim. Aby dodać rozmyte tło do okna:
Wywołaj Window#setBackgroundBlurRadius(int), aby ustawić promień rozmycia tła. Możesz też ustawić R.attr.windowBackgroundBlurRadius w motywie okna.
Ustaw R.attr.windowIsTranslucent na true, aby okno było półprzezroczyste. Rozmycie jest rysowane pod powierzchnią okna, więc okno musi być półprzezroczyste, aby rozmycie było widoczne.
Opcjonalnie wywołaj Window#setBackgroundDrawableResource(int), aby dodać prostokątny obiekt rysowalny tła okna z półprzezroczystym kolorem. Możesz też ustawić R.attr.windowBackground w motywie okna.
W przypadku okna z zaokrąglonymi rogami określ zaokrąglone rogi dla rozmytego obszaru, ustawiając ShapeDrawable z zaokrąglonymi rogami jako obiekt rysowalny tła okna.
Obsługuj stany włączenia i wyłączenia rozmycia. Więcej informacji znajdziesz w sekcji Wytyczne dotyczące używania rozmycia okna w aplikacjach.
Rozmycie za
Rozmycie za rozmywa cały ekran za oknem. Ten efekt służy do kierowania uwagi użytkownika na zawartość okna przez rozmycie wszystkiego na ekranie za oknem.
Aby rozmyć treści za oknem:
Dodaj
FLAG_BLUR_BEHINDdo flag okna, aby włączyć rozmycie za. Możesz też ustawić R.attr.windowBlurBehindEnabled w motywie okna.Wywołaj
WindowManager.LayoutParams#setBlurBehindRadius, aby ustawić promień rozmycia za. Możesz też ustawić R.attr.windowBlurBehindRadius w motywie okna.Opcjonalnie wybierz uzupełniającą wartość przyciemnienia.
Obsługuj stany włączenia i wyłączenia rozmycia. Więcej informacji znajdziesz w sekcji Wytyczne dotyczące używania rozmycia okna w aplikacjach.
Wytyczne dotyczące używania rozmycia okna w aplikacjach
Obsługa rozmycia okna zależy od tych czynników:
Wersja Androida: interfejsy API rozmycia okna są dostępne tylko w Androidzie 12 i nowszych wersjach. Sprawdź wersję Androida w pakiecie SDK urządzenia.
Wydajność grafiki: urządzenia z mniej wydajnymi procesorami graficznymi mogą nie obsługiwać rozmycia okna.
Stan systemu: serwer systemowy może tymczasowo wyłączyć rozmycie okna w czasie działania, np. w trybie oszczędzania baterii, podczas odtwarzania niektórych rodzajów treści wideo lub z powodu zastąpienia przez dewelopera.
Aby aplikacja była zgodna z różnymi wersjami Androida, urządzeniami i stanami systemu, postępuj zgodnie z tymi wytycznymi:
Dodaj odbiornik za pomocą WindowManager#addCrossWindowBlurEnabledListener, aby otrzymywać powiadomienia o włączeniu lub wyłączeniu rozmycia okna. Dodatkowo, użyj
WindowManager#isCrossWindowBlurEnabled, aby sprawdzić , czy rozmycie okna jest obecnie włączone.Zaimplementuj 2 wersje tła okna, aby uwzględnić stan włączenia lub wyłączenia rozmycia okna.
Gdy rozmycie jest włączone, tło okna powinno być półprzezroczyste, aby rozmycie było widoczne. W tym stanie, gdy rozmycie zostanie wyłączone, zawartość okna będzie bezpośrednio nakładać się na zawartość okna znajdującego się pod nim, co utrudni odczytanie nakładającego się okna. Aby uniknąć takiego efektu, gdy rozmycie okna jest wyłączone, dostosuj interfejs aplikacji w ten sposób:
W przypadku rozmycia tła zwiększ wartość alfa rysunku tła okna, aby był bardziej nieprzezroczysty.
W przypadku rozmycia za dodaj warstwę przyciemnienia z większą wartością przyciemnienia.
Przykład rozmycia za i rozmycia tła
W tej sekcji znajdziesz działający przykład aktywności, która używa zarówno rozmycia za, jak i rozmycia tła.
Poniższy przykład MainActivity.java to okno dialogowe z promieniem rozmycia za wynoszącym 20 pikseli i promieniem rozmycia tła wynoszącym 80 pikseli. Ma zaokrąglone rogi zdefiniowane w pliku XML w obiekcie rysowalnym tła okna. Prawidłowo obsługuje różne wersje Androida, różne urządzenia (które mogą nie obsługiwać rozmycia okna) oraz zmiany stanu włączenia lub wyłączenia rozmycia w czasie działania. Dzięki dostosowaniu wartości alfa obiektu rysowalnego tła okna i wartości przyciemnienia okna zapewnia, że zawartość okna dialogowego jest czytelna w każdych z tych warunków.
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;
}
}
Aby utworzyć zaokrąglone rogi okna, zdefiniuj tło okna w
res/drawable/window_background.xml jako ShapeDrawable z zaokrąglonymi rogami
o promieniu 20 dp w ten sposób:
<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle" >
<corners android:radius="20dp"/>
<solid android:color="#AAAAAA"/>
</shape>
Rozmycie okna rozmywa zawartość okna znajdującego się pod aktywnością. Rozmyty obraz jest rysowany pod tym oknem aktywności, więc okno aktywności musi być półprzezroczyste, aby rozmycie było widoczne. Aby okno było półprzezroczyste, ustaw R.attr.windowIsTranslucent w motywie aktywności w ten sposób:
<style name="Theme.BlurryDialog" parent="Theme.MaterialComponents.Dialog">
<item name="android:windowIsTranslucent">true</item>
</style>
Producenci OEM i partnerzy
Aby rozmycie okna działało na urządzeniu, producent OEM musi zadeklarować, że urządzenie obsługuje rozmycie okna.
Aby sprawdzić, czy Twoje urządzenie obsługuje rozmycie okna:
Upewnij się, że urządzenie może obsłużyć dodatkowe obciążenie procesora graficznego. Urządzenia z niższej półki mogą nie być w stanie obsłużyć dodatkowego obciążenia, co może powodować utratę klatek. Włączaj rozmycie okna tylko na przetestowanych urządzeniach z wystarczającą mocą procesora graficznego.
Jeśli masz dostosowany silnik renderowania, upewnij się, że implementuje on logikę rozmycia. Domyślny silnik renderowania Androida 12 implementuje logikę rozmycia w
BlurFilter.cpp.
Gdy upewnisz się, że Twoje urządzenie obsługuje rozmycie okna, ustaw ten
parametr systemowy surface flinger sysprop:
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
Weryfikacja
Aby sprawdzić, czy okno aplikacji jest prawidłowo obsługiwane podczas przełączania między stanami włączenia i wyłączenia rozmycia:
Otwórz interfejs, który ma rozmycie.
Włącz lub wyłącz rozmycie okna, włączając i wyłączając rozmycie okna.
Sprawdź, czy interfejs okna zmienia się na rozmyty i z powrotem zgodnie z oczekiwaniami.
Włączanie i wyłączanie rozmycia okna
Aby sprawdzić, jak interfejs okna jest renderowany z efektem rozmycia okna, włącz lub wyłącz rozmycie za pomocą jednej z tych metod:
W opcjach programisty:
Ustawienia -> System -> Opcje programisty -> Renderowanie z akceleracją sprzętową -> Zezwalaj na rozmycie na poziomie okna
W terminalu na urządzeniu z dostępem do roota:
adb shell wm disable-blur 1 # 1 disables window blurs, 0 allows them
Aby sprawdzić, czy urządzenie z Androidem 12 lub nowszym obsługuje rozmycie okna i czy jest ono obecnie włączone, uruchom adb shell wm disable-blur na urządzeniu z dostępem do roota.
Rozwiązywanie problemów
Podczas weryfikacji korzystaj z tych wskazówek dotyczących rozwiązywania problemów.
Brak rozmycia
Sprawdź, czy rozmycie jest obecnie włączone i czy Twój sprzęt je obsługuje. Więcej informacji znajdziesz w sekcji Włączanie i wyłączanie rozmycia okna.
Upewnij się, że ustawisz półprzezroczysty kolor tła okna. Nieprzezroczysty kolor tła okna ukrywa rozmyty obszar.
Urządzenie testowe nie obsługuje rozmycia okna
- Przetestuj aplikację w emulatorze Androida 12. Aby skonfigurować emulator Androida, przeczytaj artykuł Konfigurowanie emulatora Androida. Każde wirtualne urządzenie z Androidem utworzone za pomocą emulatora obsługuje rozmycie okna.
Brak zaokrąglonych rogów
- Ustaw rysunek tła okna aby zdefiniować zaokrąglone rogi. Ten obiekt rysowalny określa kontur rozmytego obszaru.
Aktualizacja opcji programisty nie włącza rozmycia
- Sprawdź, czy urządzenie jest w trybie oszczędzania baterii lub czy używa tunelowania multimediów. Na niektórych urządzeniach z Androidem TV rozmycie okna może być też wyłączone podczas odtwarzania filmów.
Rozmycie tła jest rysowane na pełnym ekranie, a nie w granicach okna
Sprawdź, czy android:windowIsFloating jest ustawione na true, aby okno było oznaczone jako pływające.
Upewnij się, że ustawiony jest rysunek tła okna. To ustawienie określa kontur rozmytego obszaru.
Aktualizacje z odbiornika nie są stosowane na ekranie
- Aktualizacje odbiornika mogą być stosowane do starej instancji okna. Sprawdź, czy okno jest niszczone i ponownie tworzone z prawidłową aktualizacją odbiornika.
