ב-Android 12, יש ממשקי API ציבוריים שמאפשרים להטמיע אפקטים של טשטוש חלונות, כמו טשטוש הרקע וטשטוש מאחורי החלון.
טשטוש חלון או טשטוש בין חלונות משמש לטשטוש המסך מאחורי החלון הנתון. יש שני סוגים של טשטוש חלונות, שאפשר להשתמש בהם כדי ליצור אפקטים ויזואליים שונים:
טשטוש הרקע מאפשר ליצור חלונות עם רקע מטושטש, כך שנוצר אפקט של זכוכית חלבית.
טשטוש הרקע מאפשר לטשטש את כל המסך מאחורי חלון (דו-שיח), כדי ליצור אפקט של עומק שדה.
אפשר להשתמש בשני האפקטים בנפרד או לשלב ביניהם, כמו שרואים באיור הבא:
a |
b |
![]() c |
איור 1. טשטוש הרקע בלבד (a), טשטוש רק של מה שמאחוריכם (b), טשטוש הרקע וגם מה שמאחוריכם (c)
התכונה 'טשטוש חלונות' פועלת בכל החלונות, כלומר היא פועלת גם אם יש אפליקציה אחרת מאחורי החלון שלכם. ההשפעה הזו שונה מאפקט הטשטוש של הרכיב, שמטשטש את התוכן בתוך אותו חלון. טשטוש החלון שימושי לתיבות דו-שיח, לגיליונות תחתונים ולחלונות צפים אחרים.
הטמעה
מפתחי אפליקציות
מפתחי אפליקציות צריכים לספק רדיוס טשטוש כדי ליצור אפקט טשטוש. רדיוס הטשטוש קובע את צפיפות הטשטוש. כלומר, ככל שהרדיוס גדול יותר, הטשטוש צפוף יותר. טשטוש של 0 פיקסלים אומר שאין טשטוש. כדי ליצור טשטוש מאחורי האובייקט, רדיוס של 20 פיקסלים יוצר אפקט טוב של עומק שדה, ורדיוס של 80 פיקסלים יוצר אפקט טוב של זכוכית חלבית. מומלץ להימנע משימוש ברדיוסים של טשטוש שגבוהים מ-150 פיקסלים, כי זה ישפיע באופן משמעותי על הביצועים.
כדי להשיג את אפקט הטשטוש הרצוי ולשפר את הקריאות, בוחרים ערך של רדיוס הטשטוש ומשלימים אותו עם שכבת צבע שקופה למחצה.
טשטוש הרקע
אתם יכולים להשתמש בטשטוש הרקע בחלונות צפים כדי ליצור אפקט רקע לחלון, שהוא תמונה מטושטשת של התוכן שמתחתיו. כדי להוסיף רקע מטושטש לחלון:
מתקשרים אל Window#setBackgroundBlurRadius(int) כדי להגדיר את רדיוס הטשטוש של הרקע. אפשר גם להגדיר את R.attr.windowBackgroundBlurRadius בעיצוב החלון.
מגדירים את R.attr.windowIsTranslucent לערך true כדי שהחלון יהיה שקוף. הטשטוש מצויר מתחת לפני השטח של החלון, ולכן החלון צריך להיות שקוף כדי שהטשטוש יהיה גלוי.
אופציונלית, אפשר לקרוא ל-Window#setBackgroundDrawableResource(int) כדי להוסיף רקע מלבני לחלון עם צבע שקוף למחצה. אפשר גם להגדיר את R.attr.windowBackground בעיצוב החלון.
כדי לקבוע את הפינות המעוגלות של האזור המטושטש בחלון עם פינות מעוגלות, צריך להגדיר ShapeDrawable עם פינות מעוגלות כמשאב ה-Drawable של רקע החלון.
טיפול במצבי טשטוש מופעל ומושבת. מידע נוסף זמין בקטע הנחיות לשימוש בטשטוש חלונות באפליקציות.
טשטוש הרקע
הטשטוש מאחורי החלון מטשטש את כל המסך מאחורי החלון. האפקט הזה משמש להפניית תשומת הלב של המשתמש לתוכן החלון על ידי טשטוש כל מה שמוצג במסך מאחורי החלון.
כדי לטשטש את התוכן שמאחורי החלון:
מוסיפים את
FLAG_BLUR_BEHINDלדגלי החלון כדי להפעיל את הטשטוש מאחורי החלון. לחלופין, מגדירים את R.attr.windowBlurBehindEnabled בעיצוב החלון.מתקשרים אל
WindowManager.LayoutParams#setBlurBehindRadiusכדי להגדיר את רדיוס הטשטוש מאחוריכם. אפשר גם להגדיר את R.attr.windowBlurBehindRadius בעיצוב החלון.אפשר גם לבחור סכום עמעום משלים.
טיפול במצבי טשטוש מופעל ומושבת. מידע נוסף זמין בקטע הנחיות לשימוש בטשטוש חלונות באפליקציות.
הנחיות לשימוש בטשטוש חלונות באפליקציות
התמיכה בטשטוש החלונות תלויה בדברים הבאים:
גרסת Android: ממשקי ה-API של טשטוש החלונות זמינים רק ב-Android מגרסה 12 ומעלה. בודקים את ה-SDK של המכשיר כדי לראות איזו גרסת Android מותקנת בו.
ביצועים גרפיים: יכול להיות שבמכשירים עם GPU עם ביצועים נמוכים יותר לא תהיה תמיכה בטשטוש חלונות.
מצב המערכת: יכול להיות ששרת המערכת ישבית באופן זמני את טשטוש החלונות בזמן הריצה, למשל במהלך מצב חיסכון בסוללה, בזמן הפעלת סוגים מסוימים של תוכן וידאו או בגלל ביטול ברירת מחדל של מפתח.
כדי שהאפליקציה תהיה תואמת לגרסאות, למכשירים ולמצבי מערכת שונים של Android, צריך לפעול לפי ההנחיות הבאות:
מוסיפים listener באמצעות WindowManager#addCrossWindowBlurEnabledListener, כדי לקבל התראה כשהטשטוש של החלון מופעל או מושבת. בנוסף, אפשר להשתמש ב-
WindowManager#isCrossWindowBlurEnabledכדי לבדוק אם טשטוש החלונות מופעל כרגע.צריך להטמיע שתי גרסאות לרקע של החלון, כדי להתאים למצב המופעל או המושבת של טשטוש החלון.
כשהטשטוש מופעל, הרקע של החלון צריך להיות שקוף כדי שהטשטוש יהיה גלוי. במצב הזה, כשהטשטוש מושבת, התוכן של החלון חופף ישירות לתוכן של החלון הבסיסי, ולכן קשה יותר לקרוא את התוכן של החלון החופף. כדי למנוע את האפקט הזה, כשמשביתים את טשטוש החלון, צריך לשנות את ממשק המשתמש של האפליקציה באופן הבא:
כדי לטשטש את הרקע, מגדילים את ערך האלפא של הרקע של חלון הציור, כדי שיהיה אטום יותר.
כדי להוסיף טשטוש מאחורי האובייקט, מוסיפים שכבה עמומה עם כמות עמעום גבוהה יותר.
דוגמה לטשטוש מאחורי האובייקט ולטשטוש הרקע
בקטע הזה מופיעה דוגמה לפעילות שבה נעשה שימוש גם בטשטוש מאחורי המשתתף וגם בטשטוש ברקע.
בדוגמה הבאה של MainActivity.java מוצג דו-שיח עם טשטוש ברקע ברדיוס של 20 פיקסלים וטשטוש ברקע ברדיוס של 80 פיקסלים. יש לו פינות מעוגלות, שמוגדרות ב-XML בפריט הניתן לציור של רקע החלון. הוא מטפל בצורה נכונה בגרסאות שונות של 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 כ-ShapeDrawable עם פינות מעוגלות ברדיוס של 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 surface flinger באופן הבא:
PRODUCT_VENDOR_PROPERTIES += \
ro.surface_flinger.supports_background_blur=1
אימות
כדי לוודא שחלון האפליקציה מטפל בצורה נכונה במעבר בין מצב שבו הטשטוש מופעל לבין מצב שבו הטשטוש מושבת, צריך לבצע את השלבים הבאים:
פותחים את ממשק המשתמש שבו רוצים להשתמש בטשטוש.
כדי להפעיל או להשבית את טשטוש החלון, מפעילים או משביתים את ההגדרה 'טשטוש החלון'.
מוודאים שממשק המשתמש של החלון משתנה למצב מטושטש וממצב מטושטש כמצופה.
הפעלה והשבתה של טשטוש החלון
כדי לבדוק איך ממשק המשתמש של החלון מוצג עם אפקט הטשטוש של החלון, מפעילים או משביתים את הטשטוש באחת מהשיטות הבאות:
באפשרויות למפתחים:
הגדרות -> מערכת -> אפשרויות למפתחים -> עיבוד עם האצת חומרה -> אפשרות לטשטוש ברמת החלון
מהטרמינל במכשיר עם הרשאות בסיס:
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 שיוצרים באמצעות האמולטור תומך בטשטוש החלון.
ללא פינות מעוגלות
- מגדירים drawable לרקע של החלון כדי להגדיר פינות מעוגלות. ה-drawable הזה קובע את המתאר של האזור המטושטש.
עדכון האפשרות למפתחים לא מפעיל את הטשטוש
- בודקים אם המכשיר במצב חיסכון בסוללה או אם הוא משתמש במנהור מולטימדיה. יכול להיות שגם טשטוש החלון יושבת בחלק ממכשירי הטלוויזיה במהלך הפעלת הסרטון.
טשטוש הרקע מוצג במסך מלא, ולא בתוך גבולות החלון
בודקים את android:windowIsFloating כדי לוודא שהחלון מסומן כחלון צף.
מוודאים שמוגדר window background drawable. ההגדרה הזו קובעת את המתאר של האזור המטושטש.
העדכונים מה-listener לא מוחלים על המסך
- יכול להיות שהעדכונים של מאזין מוחלים על מופע ישן של חלון. בודקים אם החלון נהרס ונוצר מחדש עם העדכון הנכון של listener.
