בדף הזה מתוארים שיפורים בגודל של ווידג'טים וגמישות רבה יותר שהוצגו ב-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
. בטווח הזה, תוכלו לקבוע את נקודת הסף להחלפת הפריסות.
ספק פריסות מדויקות
אם לא ניתן להשתמש בקבוצה קטנה של פריסות רספונסיביות, אפשר לספק במקום זאת פריסות שונות שמותאמות לגדלים שבהם הווידג'ט מוצג. בדרך כלל יש שני גדלים לטלפונים (במצב לאורך ובמצב לרוחב) וארבעה גדלים למכשירים מתקפלים.
כדי להטמיע את הפתרון הזה, האפליקציה צריכה לבצע את השלבים הבאים:
עומס יתר
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 | 697x51dp |
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
).
כשהמשתמש משנה את הגודל של הווידג'ט, המראה שלו משתנה בהתאם לכל גודל בתאים, כפי שמוצג בדוגמאות הבאות.