בדף הזה מוסבר על שיפורים בגודל הווידג'טים ועל גמישות רבה יותר שהוצגו ב-Android 12 (רמת API 31). בנוסף, מוסבר במאמר איך קובעים את הגודל של הווידג'ט.
שימוש בממשקי API משופרים לגדלים ולפריסות של ווידג'טים
החל מ-Android 12 (רמת API 31), אפשר לספק מאפייני גודל מדויקים יותר ופריסות גמישות יותר באמצעות הפעולות הבאות, כפי שמתואר בקטעים הבאים:
בגרסאות קודמות של Android, אפשר לקבל את טווחי הגודל של הווידג'ט באמצעות התוספים OPTION_APPWIDGET_MIN_WIDTH
, OPTION_APPWIDGET_MIN_HEIGHT
, OPTION_APPWIDGET_MAX_WIDTH
ו-OPTION_APPWIDGET_MAX_HEIGHT
, ואז להעריך את הגודל של הווידג'ט, אבל הלוגיקה הזו לא פועלת בכל המצבים. בווידג'טים שמטרגטים ל-Android 12 ואילך, מומלץ לספק פריסות דינמיות או פריסות מדויקות.
ציון אילוצים נוספים על גודל הווידג'ט
ב-Android 12 נוספו ממשקי API שמאפשרים לוודא שהגודל של הווידג'ט מותאם בצורה מהימנה יותר למכשירים שונים עם גדלי מסך שונים.
בנוסף למאפיינים הקיימים minWidth
, minHeight
, minResizeWidth
ו-minResizeHeight
, צריך להשתמש במאפיינים החדשים הבאים: appwidget-provider
.
targetCellWidth
ו-targetCellHeight
: מגדירים את גודל היעד של הווידג'ט במונחים של תאי רשת של מרכז האפליקציות. אם המאפיינים האלה מוגדרים, המערכת משתמשת בהם במקום במאפייניםminWidth
אוminHeight
.
maxResizeWidth
ו-maxResizeHeight
: מגדירים את הגודל המקסימלי שהמשתמש יכול לשנות את הגודל של הווידג'ט.
בדוגמת ה-XML הבאה אפשר לראות איך משתמשים במאפייני הגודל.
<appwidget-provider
...
android:targetCellWidth="3"
android:targetCellHeight="2"
android:maxResizeWidth="250dp"
android:maxResizeHeight="110dp">
</appwidget-provider>
יצירת פריסות רספונסיביות
אם הפריסה צריכה להשתנות בהתאם לגודל הווידג'ט, מומלץ ליצור קבוצה קטנה של פריסות, שכל אחת מהן תקפה לטווח גדלים. אם זה לא אפשרי, אפשרות נוספת היא לספק פריסות שמבוססות על הגודל המדויק של הווידג'ט בזמן הריצה, כפי שמתואר בדף הזה.
התכונה הזו מאפשרת שינוי גודל חלק יותר ושיפור כללי של תקינות המערכת, כי המערכת לא צריכה להפעיל את האפליקציה בכל פעם שהיא מציגה את הווידג'ט בגודל אחר.
בדוגמה הבאה של קוד מוצג אופן ההגדרה של רשימת פריסות.
Kotlin
override fun onUpdate(...) { val smallView = ... val tallView = ... val wideView = ... val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(150f, 100f) to smallView, SizeF(150f, 200f) to tallView, SizeF(215f, 100f) to wideView ) val remoteViews = RemoteViews(viewMapping) appWidgetManager.updateAppWidget(id, remoteViews) }
Java
@Override public void onUpdate(...) { RemoteViews smallView = ...; RemoteViews tallView = ...; RemoteViews wideView = ...; Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(150f, 100f), smallView); viewMapping.put(new SizeF(150f, 200f), tallView); viewMapping.put(new SizeF(215f, 100f), wideView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); }
נניח שלווידג'ט יש את המאפיינים הבאים:
<appwidget-provider
android:minResizeWidth="160dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="250dp"
android:maxResizeHeight="200dp">
</appwidget-provider>
קטע הקוד שלמעלה אומר:
-
smallView
160dp (minResizeWidth
) × 110dp (minResizeHeight
) עד 160dp × 199dp (נקודת החיתוך הבאה – 1dp). -
tallView
תומך בערכים מ-160dp × 200dp עד 214dp (נקודת החיתוך הבאה פחות 1) × 200dp.
wideView
תומך במידות של 215dp × 110dp (minResizeHeight
) עד 250dp (maxResizeWidth
) × 200dp (maxResizeHeight
).
הווידג'ט צריך לתמוך בטווח הגדלים מ-minResizeWidth
× minResizeHeight
עד maxResizeWidth
× maxResizeHeight
. בטווח הזה, אתם יכולים להחליט מה תהיה נקודת החיתוך למעבר בין פריסות.

הצגת פריסות מדויקות
אם לא ניתן ליצור קבוצה קטנה של פריסות רספונסיביות, אפשר במקום זאת לספק פריסות שונות שמותאמות לגדלים שבהם הווידג'ט מוצג. בדרך כלל יש שני גדלים לטלפונים (מצב לאורך ומצב לרוחב) וארבעה גדלים לטלפונים מתקפלים.
כדי להטמיע את הפתרון הזה, האפליקציה צריכה לבצע את השלבים הבאים:
Overload
AppWidgetProvider.onAppWidgetOptionsChanged()
, שמופעל כשקבוצת הגדלים משתנה.קוראים ל-
AppWidgetManager.getAppWidgetOptions()
, שמחזירהBundle
שמכילה את הגדלים.מגיעים למקש
AppWidgetManager.OPTION_APPWIDGET_SIZES
מתוךBundle
.
בדוגמה הבאה של קוד אפשר לראות איך מספקים פריסות מדויקות.
Kotlin
override fun onAppWidgetOptionsChanged( context: Context, appWidgetManager: AppWidgetManager, id: Int, newOptions: Bundle? ) { super.onAppWidgetOptionsChanged(context, appWidgetManager, id, newOptions) // Get the new sizes. val sizes = newOptions?.getParcelableArrayList<SizeF>( AppWidgetManager.OPTION_APPWIDGET_SIZES ) // Check that the list of sizes is provided by the launcher. if (sizes.isNullOrEmpty()) { return } // Map the sizes to the RemoteViews that you want. val remoteViews = RemoteViews(sizes.associateWith(::createRemoteViews)) appWidgetManager.updateAppWidget(id, remoteViews) } // Create the RemoteViews for the given size. private fun createRemoteViews(size: SizeF): RemoteViews { }
Java
@Override public void onAppWidgetOptionsChanged( Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { super.onAppWidgetOptionsChanged(context, appWidgetManager, appWidgetId, newOptions); // Get the new sizes. ArrayList<SizeF> sizes = newOptions.getParcelableArrayList(AppWidgetManager.OPTION_APPWIDGET_SIZES); // Check that the list of sizes is provided by the launcher. if (sizes == null || sizes.isEmpty()) { return; } // Map the sizes to the RemoteViews that you want. Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); for (SizeF size : sizes) { viewMapping.put(size, createRemoteViews(size)); } RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews); } // Create the RemoteViews for the given size. private RemoteViews createRemoteViews(SizeF size) { }
קביעת הגודל של הווידג'ט
כל ווידג'ט צריך להגדיר targetCellWidth
ו-targetCellHeight
למכשירים עם Android מגרסה 12 ואילך, או minWidth
ו-minHeight
לכל הגרסאות של Android, כדי לציין את כמות המקום המינימלית שהוא תופס כברירת מחדל. עם זאת, כשמשתמשים מוסיפים ווידג'ט למסך הבית, הוא בדרך כלל תופס יותר מהרוחב והגובה המינימליים שציינתם.
במסכי הבית של Android יש רשת של מקומות פנויים שבהם המשתמשים יכולים למקם ווידג'טים וסמלים. הפריסה הזו יכולה להשתנות בהתאם למכשיר. לדוגמה, בטלפונים רבים יש פריסה של 5x4, ובטאבלטים יכולה להיות פריסה גדולה יותר. כשמוסיפים את הווידג'ט, הוא מתרחב כדי לתפוס את המספר המינימלי של התאים, אופקית ואנכית, שנדרשים כדי לעמוד במגבלות של targetCellWidth
ו-targetCellHeight
במכשירים עם Android 12 ואילך, או במגבלות של minWidth
ו-minHeight
במכשירים עם Android 11 (רמת API 30) ומטה.
הרוחב והגובה של תא, וגם הגודל של השוליים האוטומטיים שמוגדרים לווידג'טים, יכולים להיות שונים במכשירים שונים. הטבלה הבאה יכולה לעזור לכם להעריך את המידות המינימליות של הווידג'ט במכשיר טיפוסי עם רשת של 5x4, בהתאם למספר התאים ברשת שאתם רוצים שהווידג'ט יתפוס:
מספר התאים (רוחב x גובה) | הגודל שזמין במצב פורטרט (dp) | הגודל הזמין במצב לרוחב (dp) |
---|---|---|
1x1 | 57x102dp | 127x51dp |
2x1 | 130x102dp | 269x51dp |
3x1 | 203x102dp | 412x51dp |
4x1 | 276x102dp | 554x51dp |
5x1 | 349x102dp | 697 x 51dp |
5x2 | 349x220dp | 697x117dp |
5x3 | 349x337dp | 697x184dp |
5x4 | 349x455dp | 697x250dp |
... | ... | ... |
n x m | (73n - 16) x (118m - 16) | (142n - 15) x (66m - 15) |
השתמשו במידות התאים במצב פורטרט כדי להזין את הערכים במאפיינים minWidth
, minResizeWidth
ו-maxResizeWidth
. באופן דומה, צריך להשתמש בגדלים של התאים במצב לרוחב כדי לקבוע את הערכים שאתם מספקים למאפיינים minHeight
, minResizeHeight
ו-maxResizeHeight
.
הסיבה לכך היא שבדרך כלל רוחב התא קטן יותר בפריסה לאורך מאשר בפריסה לרוחב, ובדומה לכך, גובה התא קטן יותר בפריסה לרוחב מאשר בפריסה לאורך.
לדוגמה, אם רוצים לשנות את הרוחב של הווידג'ט כך שיתאים לתא אחד ב-Google Pixel 4, צריך להגדיר את minResizeWidth
ל-56dp לכל היותר, כדי לוודא שהערך של המאפיין minResizeWidth
קטן מ-57dp – כי הרוחב של תא הוא לפחות 57dp במצב אנכי.
באופן דומה, אם רוצים לשנות את הגובה של הווידג'ט בתא אחד באותו מכשיר, צריך להגדיר את minResizeHeight
ל-50dp לכל היותר, כדי לוודא שהערך של המאפיין minResizeHeight
קטן מ-51dp – כי הגובה של תא אחד הוא לפחות 51dp במצב לרוחב.
אפשר לשנות את הגודל של כל ווידג'ט בטווח הגדלים שבין המאפיינים minResizeWidth
/minResizeHeight
לבין maxResizeWidth
/maxResizeHeight
, כלומר הווידג'ט צריך להתאים לכל טווח גדלים ביניהם.
לדוגמה, כדי להגדיר את גודל ברירת המחדל של הווידג'ט במיקום, אפשר להגדיר את המאפיינים הבאים:
<appwidget-provider
android:targetCellWidth="3"
android:targetCellHeight="2"
android:minWidth="180dp"
android:minHeight="110dp">
</appwidget-provider>
כלומר, גודל ברירת המחדל של הווידג'ט הוא 3x2 תאים, כפי שמצוין במאפיינים targetCellWidth
ו-targetCellHeight
, או 180x110dp, כפי שמצוין במאפיינים minWidth
ו-minHeight
למכשירים עם Android 11 או גרסאות קודמות. במקרה האחרון, הגודל בתאים יכול להיות שונה בהתאם למכשיר.
כדי להגדיר את טווחי הגדלים הנתמכים של הווידג'ט, אפשר להגדיר גם את המאפיינים הבאים:
<appwidget-provider
android:minResizeWidth="180dp"
android:minResizeHeight="110dp"
android:maxResizeWidth="530dp"
android:maxResizeHeight="450dp">
</appwidget-provider>
כפי שצוין במאפיינים הקודמים, רוחב הווידג'ט ניתן לשינוי מ-180dp ל-530dp, והגובה שלו ניתן לשינוי מ-110dp ל-450dp. אחרי זה אפשר לשנות את הגודל של הווידג'ט מ-3x2 לתאים בגודל 5x2, כל עוד מתקיימים התנאים הבאים:
- במכשיר יש רשת של 5x4.
- המיפוי בין מספר התאים לבין הגודל הזמין ביחידות dps מופיע בטבלה שבה מוצגת הערכה של המידות המינימליות בדף הזה.
- הווידג'ט מותאם לטווח הגדלים הזה.
Kotlin
val smallView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_small) val mediumView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_medium) val largeView = RemoteViews(context.packageName, R.layout.widget_weather_forecast_large) val viewMapping: Map<SizeF, RemoteViews> = mapOf( SizeF(180f, 110f) to smallView, SizeF(270f, 110f) to mediumView, SizeF(270f, 280f) to largeView ) appWidgetManager.updateAppWidget(appWidgetId, RemoteViews(viewMapping))
Java
RemoteViews smallView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_small); RemoteViews mediumView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_medium); RemoteViews largeView = new RemoteViews(context.getPackageName(), R.layout.widget_weather_forecast_large); Map<SizeF, RemoteViews> viewMapping = new ArrayMap<>(); viewMapping.put(new SizeF(180f, 110f), smallView); viewMapping.put(new SizeF(270f, 110f), mediumView); viewMapping.put(new SizeF(270f, 280f), largeView); RemoteViews remoteViews = new RemoteViews(viewMapping); appWidgetManager.updateAppWidget(id, remoteViews);
נניח שהווידג'ט משתמש בפריסות רספונסיביות שמוגדרות בקטעי הקוד הקודמים. כלומר, הפריסה שצוינה כ-R.layout.widget_weather_forecast_small
משמשת מ-180dp (minResizeWidth
) x 110dp (minResizeHeight
) עד 269x279dp (נקודות החיתוך הבאות – 1). באופן דומה,
הסמל R.layout.widget_weather_forecast_medium
משמש מ-270x110dp עד 270x279dp,
והסמל R.layout.widget_weather_forecast_large
משמש מ-270x280dp עד
530dp (maxResizeWidth
) x 450dp (maxResizeHeight
).
כשהמשתמש משנה את הגודל של הווידג'ט, המראה שלו משתנה בהתאם לכל גודל בתאים, כמו שמוצג בדוגמאות הבאות.

R.layout.widget_weather_forecast_small
.
R.layout.widget_weather_forecast_medium
.
R.layout.widget_weather_forecast_medium
.
R.layout.widget_weather_forecast_large
.
R.layout.widget_weather_forecast_large
.