טשטוש חלונות

ב-Android 12 אפשר להשתמש בממשקי API ציבוריים להטמעת אפקטים של טשטוש חלון, כמו טשטוש רקע וטשטוש רקע מאחור.

טשטוש של חלון, או טשטוש של בין חלונות, משמש לטשטוש המסך מאחורי החלון הנתון. יש שני סוגים של טשטושי חלונות שניתן להשתמש בהם כדי ליצור אפקטים חזותיים שונים:

  • טשטוש הרקע מאפשר ליצור חלונות עם רקעים מטושטשים, שיוצרים אפקט של זכוכית מט.

  • ההגדרה טשטוש מאחור מאפשרת לטשטש את כל המסך מאחורי חלון (תיבת דו-שיח), וכך ליצור אפקט של עומק שדה.

אפשר להשתמש בשני האפקטים בנפרד או יחד, כפי שמוצג באיור הבא:

טשטוש רקע בלבד

a

טשטוש הרקע בלבד

ב

טשטוש מאחורי וטשטוש הרקע

c

איור 1. טשטוש הרקע בלבד (a), טשטוש מאחוריו בלבד (b), טשטוש רקע וטשטוש מאחוריו (c)

התכונה 'טשטוש חלון' פועלת בכל החלונות, כלומר היא פועלת גם כשיש אפליקציה אחרת מאחורי החלון. האפקט הזה שונה מאפקט הרינדור עם טשטוש, שבו התוכן מטושטש בתוך אותו חלון. טשטוש חלונות שימושי בתיבות דו-שיח, בגיליונות תחתונים ובחלונות צפים אחרים.

הטמעה

מפתחי אפליקציות

מפתחי האפליקציות חייבים לספק רדיוס טשטוש כדי ליצור אפקט טשטוש. רדיוס הטשטוש קובע את מידת הצפיפות של הטשטוש. ככל שהרדיוס גדול יותר, כך הטשטוש צפוף יותר. אם מידת טשטוש היא 0 פיקסלים, אין טשטוש. לטשטוש הרקע, רדיוס של 20 פיקסלים יוצר אפקט של עומק טוב של השדה, ורדיוס של טשטוש הרקע של 80 פיקסלים יוצר אפקט טוב של זכוכית חלבית. מומלץ לא לטשטש רדיוס שגבוה מ-150 פיקסלים, כי תהיה לכך השפעה משמעותית על הביצועים.

כדי להשיג את אפקט הטשטוש הרצוי ולשפר את הקריאות, כדאי לבחור ערך של רדיוס טשטוש עם שכבת צבע שקופה.

טשטוש הרקע

אתם יכולים להשתמש בטשטוש הרקע בחלונות צפים כדי ליצור אפקט של רקע בחלון, שהוא תמונה מטושטשת של התוכן שמתחתיו. כדי להוסיף רקע מטושטש לחלון:

  1. קוראים ל-Window#setBackgroundBlurRadius(int) כדי להגדיר את רדיוס הטשטוש של הרקע. לחלופין, בעיצוב החלון, מגדירים את R.attr.windowBackgroundBlurRadius.

  2. כדי שהחלון יהיה שקוף, מגדירים את הערך של R.attr.windowIsTranslucent ל-true. הטשטוש מצויר מתחת לפני השטח של החלון, ולכן החלון צריך להיות שקוף כדי שהטשטוש יהיה גלוי.

  3. אפשר גם לקרוא ל-Window#setBackgroundDrawableResource(int) כדי להוסיף רקע מלבני לציור בצבע שקוף. לחלופין, בעיצוב החלון, מגדירים את R.attr.windowBackground.

  4. בחלון עם פינות מעוגלות, כדי לקבוע את הפינות המעוגלות של האזור המטושטש, מגדירים ShapeDrawable עם פינות מעוגלות בתור drawable של רקע החלון.

  5. טיפול במצבים של טשטוש מופעל ומושבת. מידע נוסף זמין בקטע הנחיות לשימוש בטשטוש חלון באפליקציות.

טשטוש הרקע

התכונה 'טשטוש הרקע' מטשטשת את כל המסך שמאחורי החלון. האפקט הזה משמש להפניית תשומת הלב של המשתמש לתוכן החלון על ידי טשטוש כל מה שמופיע במסך מאחורי החלון.

כדי לטשטש את התוכן שמאחורי החלון:

  1. מוסיפים את הערך FLAG_BLUR_BEHIND לדגלי החלון כדי להפעיל את הטשטוש של הרקע. לחלופין, בעיצוב החלון, מגדירים את הערך R.attr.windowBlurBehindEnabled.

  2. קוראים לפונקציה WindowManager.LayoutParams#setBlurBehindRadius כדי להגדיר את רדיוס הטשטוש שמאחורי האובייקט. בעיצוב החלון, מגדירים את R.attr.windowBlurBehindRadius.

  3. אפשר גם לבחור dim amount משלים.

  4. טיפול במצבים של טשטוש מופעל ומושבת. מידע נוסף זמין בקטע הנחיות לשימוש בהחלשה של חלונות באפליקציות.

הנחיות לשימוש בהחלקה של חלונות באפליקציות

התמיכה בהחלשה של חלונות תלויה בגורמים הבאים:

  • גרסת Android: ממשקי ה-API של טשטוש החלונות זמינים רק ב-Android מגרסה 12 ואילך. כדאי לבדוק את ה-SDK של המכשיר כדי לראות את גרסת Android.

  • ביצועי הגרפיקה: במכשירים עם מעבדי GPU שמניבים ביצועים פחות טובים, יכול להיות שלא תהיה תמיכה בטשטוש חלונות.

  • מצב המערכת: שרת המערכת עשוי להשבית באופן זמני את טשטוש החלונות בזמן הריצה, למשל בזמן מצב חיסכון בסוללה, בזמן הפעלה של סוגים מסוימים של תוכן וידאו או בגלל שינוי מברירת המחדל של המפתח.

כדי שהאפליקציה תתאים לכל הגרסאות של Android, למכשירים ולמצבי המערכת, צריך לפעול לפי ההנחיות הבאות:

  • אתם יכולים להוסיף האזנה דרך WindowManager#addCrossWindowBlurEnabledListener, כדי להודיע לכם כשטשטוש החלון מופעל או מושבת. בנוסף, משתמשים ב-WindowManager#isCrossWindowBlurEnabled כדי לבדוק אם מופעלים כרגע טשטושי חלונות.

  • מטמיעים שתי גרסאות לרקע החלון, כדי להתאים את מצב הטשטוש של החלון למצב מופעל או מושבת.

    כשמפעילים את הטשטוש, רקע החלון צריך להיות שקוף כדי שהטשטוש יהיה גלוי. במצב הזה, כשהטשטושים מושבתים, תוכן החלון חופף ישירות לתוכן של החלון שמתחתיו, וכתוצאה מכך קשה יותר לקרוא את התוכן בחלון החופף. כדי למנוע השפעה כזו, כשטשטוש הרקע של החלון מושבת, צריך לשנות את ממשק המשתמש של האפליקציה באופן הבא:

    • כדי לטשטש את הרקע, צריך להגדיל את ערך האלפא של drawable של רקע החלון, כך שהוא יהיה אטום יותר.

    • כדי לטשטש מאחור, מוסיפים שכבה מעומעמת עם מעט יותר צבע מעומעם.

דוגמה לטשטוש מאחור וטשטוש רקע

בקטע הזה מוצגת דוגמה לפעילות שבה נעשה שימוש גם בטשטוש של הרקע וגם בטשטוש של הרקע שמאחורי הנושא.

הדוגמה הבאה של MainActivity.java היא תיבת דו-שיח עם טשטוש מאחורי רדיוס של 20 פיקסלים ורדיוס טשטוש של 80 פיקסלים. יש לו פינות מעוגלות, שמוגדרות ב-XML ב-drawable של רקע החלון. הוא מטפל בצורה נכונה בגרסאות Android שונות, במכשירים שונים (שעשויים שלא תומכים בטשטושי חלון) ובשינויים שמופעלים או מושבתים במסגרת טשטוש בזמן הריצה. כך אפשר להבטיח שהתוכן של תיבת הדו-שיח קריא בכל אחד מהתנאים האלה על ידי שינוי האלפא של חלון האלפא שאפשר לצייר ברקע של החלון וגודל עמעום החלון.

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

כדי ליצור פינות מעוגלות לחלון, מגדירים את רקע החלון ב-res/drawable/window_background.xml כ-FormDrawable עם פינות מעוגלות ברדיוס של 20 dp באופן הבא:

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

טשטוש של תוכן החלון מטשטש את תוכן החלון מתחת לפעילות. התמונה המטושטשת מצוירת מתחת לחלון הפעילות הזה, לכן חלון הפעילות צריך להיות שקוף כדי לאפשר לראות את הטשטוש. כדי שהחלון יהיה שקוף, הגדרנו את R.attr.windowIsTranslucent בעיצוב הפעילות באופן הבא:

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

יצרני ציוד מקורי (OEM) ושותפים

כדי לטשטש חלונות במכשיר, יצרן הציוד המקורי צריך להצהיר שהמכשיר תומך בטשטוש חלונות.

כדי לבדוק אם המכשיר שלכם תומך בטשטושי חלונות, מבצעים את הפעולות הבאות:

  • מוודאים שהמכשיר יכול להתמודד עם העומס הנוסף על ה-GPU. יכול להיות שמכשירים ברמה נמוכה יותר לא יוכלו להתמודד עם העומס הנוסף, וכתוצאה מכך יהיו פריימים חסרים. כדאי להפעיל את טשטוש החלונות רק במכשירים שנבדקו עם מספיק כוח GPU.

  • אם יש לכם מנוע רינדור מותאם אישית, ודאו שמנוע העיבוד מטמיע את לוגיקת הטשטוש. מנוע הרינדור שמוגדר כברירת מחדל ב-Android 12 מטמיע את הלוגיקה של הטשטוש ב-BlurFilter.cpp.

אחרי שמוודאים שהמכשיר תומך בטשטוש הרקע של החלון, הגדירו את הניגון הבא: sysprop:

PRODUCT_VENDOR_PROPERTIES += \
       ro.surface_flinger.supports_background_blur=1

אימות

כדי לוודא שחלון האפליקציה מטופל כראוי במעבר בין המצבים 'טשטוש מופעל' ו'טשטוש מושבת', מבצעים את הפעולות הבאות:

  1. פותחים את ממשק המשתמש עם הטשטוש.

  2. כדי להפעיל או להשבית את טשטושי החלונות, מפעילים ומשביתים את טשטוש החלון.

  3. מוודאים שממשק המשתמש של החלון משתנה למצב מטושטש ומצופה ממנו.

הפעלה והשבתה של טשטוש החלון

כדי לבדוק איך ממשק המשתמש של החלון מעובד עם האפקט של טשטוש החלון, מפעילים או משביתים את הטשטוש באחת מהשיטות הבאות:

  • מתוך 'אפשרויות למפתחים':

    הגדרות -> מערכת -> אפשרויות למפתחים -> עיבוד מואץ חומרה -> אישור טשטוש ברמת החלון

  • מהמסוף במכשיר עם הרשאות בסיס:

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

כדי לבדוק אם במכשיר Android 12 ואילך יש תמיכה בטשטוש חלונות ואם התכונה 'טשטוש חלונות' מופעלת כרגע, מפעילים את הפקודה adb shell wm disable-blur במכשיר עם הרשאות בסיס.

פתרון בעיות

תוכלו להיעזר במדריך הבא לפתרון בעיות במהלך האימות.

לא סומן טשטוש

  • יש לוודא שהטשטוש מופעל כרגע ושהחומרה שלך תומכת בהם. אפשר להיעזר במאמר הפעלה והשבתה של טשטוש החלון.

  • חשוב להגדיר צבע רקע שקוף לחלון. צבע רקע של חלון אטום מסתיר את האזור המטושטש.

המכשיר לבדיקה לא תומך בהחלשות חלונות

  • בודקים את האפליקציה באמולטור של Android 12. במאמר הגדרת אמולטור של Android מוסבר איך מגדירים אמולטור של Android. כל מכשיר וירטואלי של Android שיוצרים באמצעות האמולטור תומך בטשטוש החלון.

ללא פינות מעוגלות

עדכון האפשרות למפתחים לא מאפשר טשטושים

  • בודקים אם המכשיר נמצא במצב חיסכון בסוללה או אם הוא משתמש במנהור מולטימדיה. במכשירי טלוויזיה מסוימים, יכול להיות שטשטוש החלונות מושבת גם במהלך הפעלת סרטונים.

טשטוש הרקע נפתח במסך מלא, לא בתוך גבולות החלון

העדכונים מהמאזין לא חלים על המסך

  • יכול להיות שהעדכונים של המאזין חלים על מכונה ישנה של חלון. בודקים אם החלון מושמד ונוצר מחדש באמצעות עדכון המאזינים הנכון.