בדף הזה מתוארים שיפורים לשינוי הגודל של הווידג'טים וגמישות רבה יותר. הושקו ב-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>
יצירת פריסות רספונסיביות
אם הפריסה צריכה להשתנות בהתאם לגודל הווידג'ט, מומלץ יצירת קבוצה קטנה של פריסות, שכל אחת מהן מתאימה למגוון גדלים. אם אי אפשר לעשות זאת, אפשרות אחרת היא לספק פריסות על סמך הגודל המדויק של הווידג'ט בזמן הריצה, כפי שמתואר בדף הזה.
התכונה הזו מאפשרת התאמה לעומס (scaling) בצורה חלקה יותר ומערכת טובה יותר באופן כללי תקינות, כי המערכת לא צריכה להוציא את האפליקציה ממצב שינה בכל פעם והווידג'ט מוצג בגודל שונה.
הקוד לדוגמה הבא מראה איך לספק רשימת פריסות.
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) × 200dpwideView
תומך בגדלים של 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
– או 180×110dp,
צוין על ידי 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
).
כשהמשתמש משנה את הגודל של הווידג'ט, המראה שלו משתנה בהתאם לכל גודל בתאים, כפי שמוצג בדוגמאות הבאות.