בקטעים הבאים מוסבר איך ליצור ווידג'ט בסיסי לאפליקציה באמצעות Glance.
הצהרה על AppWidget בקובץ המניפסט
אחרי שמבצעים את שלבי ההגדרה, צריך להצהיר על AppWidget ועל המטא-נתונים שלו באפליקציה.
הארכת המינוי של מקלט
AppWidgetמ-GlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
רושמים את הספק של הווידג'ט של האפליקציה בקובץ
AndroidManifest.xmlובקובץ המטא-נתונים המשויך:<receiver android:name=".glance.MyReceiver" android:exported="true"> <intent-filter> <action android:name="android.appwidget.action.APPWIDGET_UPDATE" /> </intent-filter> <meta-data android:name="android.appwidget.provider" android:resource="@xml/my_app_widget_info" /> </receiver>
הוספת המטא-נתונים AppWidgetProviderInfo
לאחר מכן, פועלים לפי ההוראות במדריך יצירת ווידג'ט כדי ליצור ולהגדיר את פרטי הווידג'ט של האפליקציה בקובץ @xml/my_app_widget_info.
ההבדל היחיד ב-Glance הוא שאין קובץ XML initialLayout, אבל אתם חייבים להגדיר אחד. אפשר להשתמש בפריסת הטעינה המוגדרת מראש שמופיעה בספרייה:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
הצהרה על קובץ ה-XML של AppWidgetProviderInfo
אובייקט AppWidgetProviderInfo מגדיר את התכונות החיוניות של הווידג'ט. מגדירים את AppWidgetProviderInfo בקובץ משאבי המטא-נתונים בפורמט XML (res/xml/my_app_widget_info.xml) בתוך רכיב <appwidget-provider>:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="40dp"
android:minHeight="40dp"
android:targetCellWidth="1"
android:targetCellHeight="1"
android:maxResizeWidth="250dp"
android:maxResizeHeight="120dp"
android:updatePeriodMillis="86400000"
android:description="@string/example_appwidget_description"
android:previewLayout="@layout/example_appwidget_preview"
android:initialLayout="@layout/glance_default_loading_layout"
android:configure="com.example.android.ExampleAppWidgetConfigurationActivity"
android:resizeMode="horizontal|vertical"
android:widgetCategory="home_screen"
android:widgetFeatures="reconfigurable|configuration_optional">
</appwidget-provider>
מאפייני גודל הווידג'ט
ברירת המחדל של מיקומי הווידג'טים במסך הבית היא בחלון שמבוסס על רשת של תאים עם גובה ורוחב מוגדרים. ברוב מסכי הבית אפשר להגדיר לווידג'טים רק גדלים שהם כפולות של מספר שלם של התאים ברשת – למשל, שני תאים לרוחב ושלושה תאים לאורך.
מאפייני הגודל של הווידג'ט מאפשרים לכם לציין גודל ברירת מחדל לווידג'ט ולספק גבולות תחתונים ועליונים לגודל הווידג'ט. בהקשר הזה, גודל ברירת המחדל של הווידג'ט הוא הגודל שלו כשהוא מתווסף למסך הבית בפעם הראשונה.
בטבלה הבאה מפורטים מאפייני <appwidget-provider> שקשורים לגודל הווידג'ט:
| מאפיינים ותיאור | |
|---|---|
targetCellWidth ו-
targetCellHeight (Android 12),
minWidth ו-minHeight |
targetCellWidth ו-targetCellHeight, וגם minWidth ו-minHeight – כדי שהאפליקציה תוכל לחזור לשימוש ב-minWidth וב-minHeight אם המכשיר של המשתמש לא תומך ב-targetCellWidth וב-targetCellHeight. אם המאפיינים targetCellWidth ו-targetCellHeight נתמכים, הם מקבלים קדימות על פני המאפיינים minWidth ו-minHeight.
|
minResizeWidth וגם
minResizeHeight |
מציינים את הגודל המינימלי המוחלט של הווידג'ט. הערכים האלה מציינים את הגודל שמתחתיו הווידג'ט לא קריא או לא שמיש. השימוש במאפיינים האלה מאפשר למשתמש לשנות את גודל הווידג'ט לגודל קטן יותר מגודל ברירת המחדל של הווידג'ט. המערכת מתעלמת מהמאפיין minResizeWidth אם הוא גדול מ-minWidth או אם לא מופעלת אפשרות שינוי הגודל האופקי. מידע נוסף מפורט בresizeMode. באופן דומה, המערכת מתעלמת מהמאפיין minResizeHeight אם הוא גדול מ-minHeight או אם לא מופעלת האפשרות לשינוי גודל אנכי. |
maxResizeWidth וגם
maxResizeHeight |
מציינים את הגודל המקסימלי המומלץ של הווידג'ט. אם הערכים לא מתחלקים בגודל התאים ברשת, הם יעוגלו כלפי מעלה לגודל התא הקרוב ביותר. המערכת מתעלמת מהמאפיין maxResizeWidth אם הוא קטן מ-minWidth או אם לא מופעלת שינוי גודל אופקי. מידע נוסף מפורט בresizeMode. באופן דומה, המערכת מתעלמת מהמאפיין maxResizeHeight אם הוא קטן מ-minHeight או אם לא מופעלת אפשרות לשינוי גודל אנכי.
הוצג ב-Android 12. |
resizeMode |
מציינת את הכללים שלפיהם אפשר לשנות את הגודל של הווידג'ט. אתם יכולים להשתמש במאפיין הזה כדי לאפשר שינוי גודל של ווידג'טים במסך הבית לרוחב, לאורך או בשני הצירים. המשתמשים לוחצים לחיצה ארוכה על הווידג'ט כדי להציג את נקודות האחיזה לשינוי הגודל, ואז גוררים את נקודות האחיזה האופקיות או האנכיות כדי לשנות את הגודל שלו ברשת הפריסה. הערכים של מאפיין resizeMode כוללים את האפשרויות horizontal, vertical ו-none. כדי להגדיר שאפשר לשנות את הגודל של הווידג'ט לרוחב ולאורך, משתמשים בתג horizontal|vertical. |
דוגמה
כדי להמחיש איך המאפיינים בטבלה הקודמת משפיעים על גודל הווידג'ט, נניח שיש את המפרטים הבאים:
- הרוחב של תא ברשת הוא 30dp והגובה שלו הוא 50dp.
- מפרט המאפיינים הבא מסופק:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:minWidth="80dp"
android:minHeight="80dp"
android:targetCellWidth="2"
android:targetCellHeight="2"
android:minResizeWidth="40dp"
android:minResizeHeight="40dp"
android:maxResizeWidth="120dp"
android:maxResizeHeight="120dp"
android:resizeMode="horizontal|vertical" />
החל מ-Android 12:
משתמשים במאפיינים targetCellWidth ו-targetCellHeight כדי להגדיר את גודל ברירת המחדל של הווידג'ט.
גודל הווידג'ט הוא 2x2 כברירת מחדל. אפשר לשנות את הגודל של הווידג'ט ל-2x1 או ל-4x3.
Android מגרסה 11 ומטה:
כדי לחשב את גודל ברירת המחדל של הווידג'ט, משתמשים במאפיינים minWidth ו-minHeight.
רוחב ברירת המחדל = Math.ceil(80 / 30) = 3
גובה ברירת המחדל = Math.ceil(80 / 50) = 2
גודל הווידג'ט הוא 3x2 כברירת מחדל. אפשר לשנות את הגודל של הווידג'ט ל-2x1 או למסך מלא.
מאפיינים נוספים של ווידג'טים
בטבלה הבאה מתוארים מאפייני <appwidget-provider> שקשורים לתכונות אחרות מלבד גודל הווידג'ט.
| מאפיינים ותיאור | |
|---|---|
updatePeriodMillis |
ההגדרה הזו קובעת את התדירות שבה מסגרת הווידג'טים מבקשת עדכון מ-GlanceAppWidgetReceiver על ידי קריאה לשיטת הקריאה החוזרת onUpdate(). כדי לחסוך בסוללה, מומלץ לעדכן את המיקום בתדירות נמוכה ככל האפשר – לא יותר מפעם בשעה.
פרטים נוספים זמינים בקטע מתי לעדכן ווידג'טים במאמר בנושא ניהול מצב של תצוגה מהירה. |
initialLayout |
מצביע על משאב הפריסה שמגדיר את פריסת הטעינה של הווידג'ט לפני שהקומפוזיציות של ממשק המשתמש של Glance מעובדות. אפשר להשתמש בפריסת הטעינה המוגדרת מראש שמופיעה בספרייה: @layout/glance_default_loading_layout. |
configure |
הפעילות הזו מגדירה את ההגדרות שמוצגות למשתמש כשהוא מוסיף את הווידג'ט. אפשר לעיין במדריך בנושא הטמעת פעילות ההגדרה. |
description |
מציינים את התיאור של הווידג'ט שיוצג בכלי לבחירת ווידג'טים. הוצג ב-Android 12. |
previewLayout (Android 12)
ו-previewImage (Android מגרסה 11 ומטה) |
|
autoAdvanceViewId |
מציין את מזהה התצוגה של תצוגת המשנה של הווידג'ט, שמועברת אוטומטית על ידי המארח של הווידג'ט. |
widgetCategory |
הצהרה אם אפשר להציג את הווידג'ט במסך הבית (home_screen), במסך הנעילה (keyguard) או בשניהם. ב-Android מגרסה 5.0 ואילך, רק home_screen תקף. |
widgetFeatures |
הצהרה על תכונות שנתמכות בווידג'ט. לדוגמה, אם ההגדרה של הווידג'ט היא אופציונלית, צריך לציין גם את configuration_optional וגם את reconfigurable. |
מה ההגדרה של GlanceAppWidget
יוצרים מחלקה חדשה שמתרחבת מ-
GlanceAppWidgetומבטלת את השיטהprovideGlance. זו השיטה שבה אפשר לטעון נתונים שנדרשים לעיבוד הווידג'ט:class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // In this method, load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here Text("Hello World") } } }
יוצרים מופע שלו ב-
glanceAppWidgetב-GlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
הגדרתם עכשיו AppWidget באמצעות Glance.
שימוש במחלקה GlanceAppWidgetReceiver כדי לטפל בשידורים של הווידג'ט
ווידג'ט הקואורדינטות GlanceAppWidgetReceiver משדר עדכונים לגבי מצב הפלטפורמה על ידי הרחבת AppWidgetProvider הבסיסי. הוא מקבל אירועים של הפלטפורמה כשהווידג'ט מתעדכן, נמחק, מופעל או מושבת, ומתרגם אותם לבקשות של מחזור החיים של Compose.
הצהרה על ווידג'ט במניפסט
מצהירים על מחלקת המשנה של המחלקה GlanceAppWidgetReceiver כמקלט שידור בקובץ AndroidManifest.xml:
<receiver android:name="MyReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="@xml/my_app_widget_info" />
</receiver>
אלמנט <receiver> דורש את המאפיין android:name, שמציין את מחלקת המקלט. הנמען צריך לאשר את פעולת השידור ACTION_APPWIDGET_UPDATE בתוך <intent-filter>.
ברכיב <meta-data> צריך לציין את השם שלו כ-android.appwidget.provider, ובמאפיין android:resource צריך להפנות למשאב המטא-נתונים של XML של AppWidgetProviderInfo (@xml/my_app_widget_info).
הטמעה של המחלקה GlanceAppWidgetReceiver
ב-Glance, אתם מרחיבים את GlanceAppWidgetReceiver במקום את AppWidgetProvider ישירות. כדי להטמיע את המקלט, מקשרים אותו למופע GlanceAppWidget. ההתקשרות החוזרת העיקרית שזמינה ב-GlanceAppWidgetReceiver פועלת באופן הבא:
-
onUpdate(): המערכת מחליפה את הערך הזה באופן אוטומטי ב-Glance כדי לבצע עדכונים של קומפוזיציה. אם אתם מבטלים את ברירת המחדל שלonUpdateבאופן ידני, אתם צריכים להפעיל אתsuper.onUpdateכדי לאפשר ל-Glance להפעיל בהצלחה שרשורים של הרכבה. -
onAppWidgetOptionsChanged(): מופעל כשממקמים את הווידג'ט בפעם הראשונה או כשמשנים את הגודל שלו. האפשרויות של קריאה מהירה מאגדות פריטים מתחת לפני השטח, כך שהפריסה מותאמת בצורה חלקה על סמך המאפיינים בזמן הריצה. -
onDeleted(Context, IntArray): מופעל בכל פעם שמשתמש מוחק מופע ספציפי של ווידג'ט. -
onEnabled(Context): מופעל כשהמופע הראשון של הווידג'ט נוצר בהצלחה. מצוין להפעלת העברות גלובליות. -
onDisabled(Context): מופעלת כשמסירים את המופע הפעיל האחרון של הספק. -
onReceive(Context, Intent): חסימת כל שידור בפלטפורמה לפני שיטות קריאה חוזרת ספציפיות. צריך לוודא שכל לוגיקה מותאמת אישית של מקלט שכותבים קוראת ל-super.onReceive(context, intent), ואף פעם לא קוראת ל-goAsyncבעצמה, כי Glance מעבירה עבודה באופן אסינכרוני.
קבלת כוונות שידור של ווידג'טים
מתחת לפני השטח, GlanceAppWidgetReceiver מסנן את כוונות השידור של הווידג'טים הבסיסיים של הפלטפורמה ומטפל בהן:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
יצירת ממשק משתמש
בקטע הקוד הבא אפשר לראות איך יוצרים את ממשק המשתמש:
/* Import Glance Composables In the event there is a name clash with the Compose classes of the same name, you may rename the imports per https://kotlinlang.org/docs/packages.html#imports using the `as` keyword. import androidx.glance.Button import androidx.glance.layout.Column import androidx.glance.layout.Row import androidx.glance.text.Text */ class MyAppWidget : GlanceAppWidget() { override suspend fun provideGlance(context: Context, id: GlanceId) { // Load data needed to render the AppWidget. // Use `withContext` to switch to another thread for long running // operations. provideContent { // create your AppWidget here MyContent() } } @Composable private fun MyContent() { Column( modifier = GlanceModifier.fillMaxSize(), verticalAlignment = Alignment.Top, horizontalAlignment = Alignment.CenterHorizontally ) { Text(text = "Where to?", modifier = GlanceModifier.padding(12.dp)) Row(horizontalAlignment = Alignment.CenterHorizontally) { Button( text = "Home", onClick = actionStartActivity<MyActivity>() ) Button( text = "Work", onClick = actionStartActivity<MyActivity>() ) } } } }
דוגמת הקוד שלמעלה מבצעת את הפעולות הבאות:
- ברמה העליונה
Column, הפריטים מוצבים אחד אחרי השני באופן אנכי. - הגודל של
Columnמתרחב כדי להתאים לשטח הזמין (באמצעותGlanceModifier), והתוכן שלו מיושר לחלק העליון (verticalAlignment) ומומרכז אופקית (horizontalAlignment). - התוכן של
Columnמוגדר באמצעות lambda. הסדר חשוב.
אתם יכולים לשנות את ערכי היישור או להחיל ערכי שינוי שונים (כמו ריווח פנימי) כדי לשנות את המיקום והגודל של הרכיבים. רשימה מלאה של הרכיבים, הפרמטרים והמשנים הזמינים לכל מחלקה מופיעה במסמכי העזר.
הטמעה של פינות מעוגלות
ב-Android 12 נוספו פרמטרים של המערכת להתאמה דינמית של רדיוס הפינות של הווידג'טים של האפליקציה:
-
system_app_widget_background_radius: מציין את רדיוס הפינות של קונטיינר הרקע של הווידג'ט (לעולם לא גדול מ-28dp). - רדיוס פנימי: כדי למנוע חיתוך של התוכן, צריך לחשב רדיוס יחסי לתוכן הפנימי על סמך המתאר של הרקע במערכת:
systemRadiusValue - widgetPadding
ב-Glance, אפשר להחיל מאפייני גודל של רדיוסים של פינות באופן דינמי בקומפוזיציה באמצעות GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
כדי לשמור על תאימות לדורות קודמים במכשירים עם Android 11 (רמת API 30) ומטה, צריך להטמיע מאפיינים מותאמים אישית ומשאבי עיצוב מותאמים אישית כגיבוי:
/values/attrs.xml<resources> <attr name="backgroundRadius" format="dimension" /> </resources>/values/styles.xml<resources> <style name="MyWidgetTheme"> <item name="backgroundRadius">@dimen/my_background_radius_dimen</item> </style> </resources>/values-31/styles.xml<resources> <style name="MyWidgetTheme" parent="@android:style/Theme.DeviceDefault.DayNight"> <item name="backgroundRadius">@android:dimen/system_app_widget_background_radius</item> </style> </resources>/drawable/my_widget_background.xml<shape xmlns:android="http://schemas.android.com/apk/res/android" android:shape="rectangle"> <corners android:radius="?attr/backgroundRadius" /> </shape>