הוספת תצוגות מקדימות שנוצרו לבחירת הווידג'טים

תצוגות מקדימות של ווידג'טים שנוצרו מאפשרות לכם ליצור תצוגות מקדימות דינמיות ומותאמות אישית לווידג'טים שלכם, שמשקפות בצורה מדויקת את האופן שבו הם יופיעו במסך הבית של המשתמש. התצוגה המקדימה מסופקת באמצעות API של הודעות Push, כלומר האפליקציה מספקת את התצוגה המקדימה בכל נקודה במהלך מחזור החיים שלה, בלי לקבל בקשה מפורשת ממארח הווידג'ט.

כדי לשפר את חוויית השימוש בכלי לבחירת הווידג'טים באפליקציה, כדאי לספק תצוגה מקדימה של הווידג'ט שנוצר במכשירי Android מגרסה 15 ואילך, תצוגה מקדימה של הווידג'ט בהתאמת גודל (על ידי ציון previewLayout) במכשירי Android מגרסה 12 עד גרסה 14, וpreviewImage בגרסאות קודמות.

מידע נוסף זמין במאמר Enrich your app with live updates and widgets (הוספת עדכונים בזמן אמת ווידג'טים לאפליקציה) ב-YouTube.

הגדרת האפליקציה לתצוגות מקדימות של ווידג'טים שנוצרו

כדי להציג תצוגה מקדימה של ווידג'טים שנוצרו ב-Android 15 או בגרסאות מאוחרות יותר, צריך קודם להגדיר את הערך compileSdk ל-35 או לערך מאוחר יותר בקובץ המודול build.gradle כדי לאפשר הצגה של RemoteViews בכלי לבחירת הווידג'טים.

אחרי כן, אפליקציות יכולות להשתמש ב-setWidgetPreview ב-GlanceAppWidgetManager או ב-AppWidgetManager. כדי למנוע ניצול לרעה ולצמצם את הסיכונים לבריאות המערכת, setWidgetPreview הוא API עם הגבלת קצב של יצירת בקשות. מגבלת ברירת המחדל היא בערך שתי שיחות בשעה.

יצירת תצוגה מקדימה מעודכנת באמצעות Jetpack Glance

כדי להוסיף ווידג'טים שנוצרו באמצעות Jetpack Glance:

  1. מבטלים את ההגדרה של הפונקציה GlanceAppWidget.providePreview כדי לספק את התוכן שניתן להרכבה לתצוגה המקדימה. כמו ב-provideGlance, טוענים את הנתונים של האפליקציה ומעבירים אותם לרכיב ה-Composable של תוכן הווידג'ט, כדי לוודא שהתצוגה המקדימה מציגה נתונים מדויקים. בניגוד ל-provideGlance, זהו קומפוזיציה יחידה ללא קומפוזיציה מחדש או אפקטים.

  2. מתקשרים אל GlanceAppWidgetManager.setWidgetPreviews כדי ליצור ולפרסם את התצוגה המקדימה.

אין קריאה חוזרת מהמערכת כדי לספק תצוגות מקדימות, ולכן האפליקציה צריכה להחליט מתי להתקשר אל setWidgetPreviews. אסטרטגיית העדכון תלויה בתרחיש לדוגמה של הווידג'ט:

  • אם הווידג'ט מכיל מידע סטטי או שהוא פעולה מהירה, צריך להגדיר את התצוגה המקדימה כשהאפליקציה מופעלת בפעם הראשונה.
  • אפשר להגדיר את התצוגה המקדימה אחרי שיש נתונים באפליקציה, למשל אחרי שהמשתמש נכנס לחשבון או אחרי ההגדרה הראשונית.
  • אפשר להגדיר משימה תקופתית לעדכון התצוגות המקדימות בקצב שתבחרו.

פתרון בעיות בתצוגות מקדימות שנוצרו

בעיה נפוצה היא שאחרי שיוצרים תצוגה מקדימה, יכול להיות שחסרים בתמונה המקדימה תמונות, סמלים או רכיבים אחרים בהשוואה לגודל של הווידג'ט. גודל החלון הנפתח מוגדר על ידי targetCellWidth ו-targetCellHeight אם הם מצוינים, או על ידי minWidth ו-minHeight בקובץ המידע של ספק הווידג'ט של האפליקציה.

הסיבה לכך היא שב-Android, כברירת מחדל, מוצגים רק רכיבי composable שגלויים בגודל המינימלי של הווידג'ט. במילים אחרות, מערכת Android מגדירה את previewSizeMode כ-SizeMode.Single כברירת מחדל. הוא משתמש ב-android:minHeight וב-android:minWidth בקובץ ה-XML של ספק הווידג'ט של האפליקציה כדי לקבוע אילו רכיבים ניתנים להצגה.

כדי לפתור את הבעיה, צריך לבטל את ההגדרה של previewSizeMode ב-GlanceAppWidget ולהגדיר אותה ל-SizeMode.Responsive, תוך ציון קבוצה של ערכי DpSize. כך מערכת Android יודעת את כל גדלי הפריסה שהיא צריכה לעבד לתצוגה המקדימה, ומוודאת שכל הרכיבים יוצגו בצורה נכונה.

אופטימיזציה לגורמי צורה ספציפיים. צריך לציין גודל אחד או שניים החל מהגודל המינימלי, בהתאם לנקודות ההפסקה של הווידג'ט. צריך לציין לפחות תמונה אחת לצורך תאימות לאחור. בהנחיות לעיצוב ווידג'טים מפורטים ערכי ה-DP המינימליים המתאימים לגדלים שונים של רשתות.

יצירת תצוגה מקדימה מעודכנת בלי Jetpack Glance

אפשר להשתמש ב-RemoteViews בלי Glance. בדוגמה הבאה נטען משאב פריסת ווידג'ט בפורמט XML והוא מוגדר כתצוגה מקדימה. כדי שהפונקציה setWidgetPreview תוצג כשיטה בקטע הקוד הזה, צריך להגדיר את הגדרת ה-build של compileSdk ל-35 ומעלה.

AppWidgetManager.getInstance(appContext).setWidgetPreview(
    ComponentName(
        appContext,
        ExampleAppWidgetReceiver::class.java
    ),
    AppWidgetProviderInfo.WIDGET_CATEGORY_HOME_SCREEN,
    RemoteViews("com.example", R.layout.widget_preview)
)

הוספת תצוגה מקדימה של ווידג'טים שניתן לשנות את הגודל שלהם לכלי לבחירת ווידג'טים

החל מ-Android 12, אפשר לשנות את הגודל של התצוגה המקדימה של הווידג'ט שמוצגת בכלי לבחירת הווידג'טים. אתם מספקים אותו כפריסת XML שמוגדרת לגודל ברירת המחדל של הווידג'ט. בעבר, התצוגה המקדימה של הווידג'ט הייתה משאב סטטי של ציור, ובמקרים מסוימים התצוגות המקדימות לא שיקפו בצורה מדויקת את המראה של הווידג'טים כשהם נוספו למסך הבית.

כדי להטמיע תצוגות מקדימות של ווידג'טים שניתן לשנות את הגודל שלהם, משתמשים במאפיין previewLayout של רכיב appwidget-provider כדי לספק פריסת XML במקום זאת:

<appwidget-provider
    android:previewLayout="@layout/my_widget_preview">
</appwidget-provider>

מומלץ להשתמש באותה פריסה כמו בווידג'ט בפועל, עם ערכי ברירת מחדל או ערכי בדיקה ריאליסטיים. רוב האפליקציות משתמשות באותם previewLayout וinitialLayout. בקטע הבא בדף הזה מוסבר איך ליצור פריסות מדויקות של תצוגה מקדימה.

מומלץ לציין את המאפיינים previewLayout ו-previewImage, כדי שהאפליקציה תוכל להשתמש ב-previewImage אם המכשיר של המשתמש לא תומך ב-previewLayout. המאפיין previewLayout מקבל עדיפות על פני המאפיין previewImage.

תאימות לאחור עם תצוגות מקדימות של ווידג'טים

כדי לאפשר לכלי לבחירת ווידג'טים ב-Android 11 (רמת API 30) ומטה להציג תצוגות מקדימות של הווידג'ט שלכם, או כגיבוי לתצוגות מקדימות שנוצרו, מציינים את המאפיין previewImage.

אם משנים את המראה של הווידג'ט, צריך לעדכן את תמונת התצוגה המקדימה.

יצירת תצוגות מקדימות מדויקות שכוללות פריטים דינמיים

איור 1: תצוגה מקדימה של ווידג'ט שלא מציג פריטים ברשימה.

בקטע הזה מוסבר על הגישה המומלצת להצגת כמה פריטים בתצוגה מקדימה של ווידג'ט עם תצוגת אוסף – כלומר, ווידג'ט שמשתמש ב-ListView, GridView או StackView. הכלל הזה לא חל על תצוגות מקדימות של ווידג'טים שנוצרו.

אם הווידג'ט משתמש באחד מהתצוגות האלה, יצירת תצוגה מקדימה שניתנת להתאמה על ידי אספקת פריסת הווידג'ט בפועל תפגע בחוויה אם בתצוגה המקדימה של הווידג'ט לא יוצגו פריטים. זה קורה כי נתוני תצוגת האוסף מוגדרים באופן דינמי בזמן הריצה, והם דומים לתמונה שמוצגת באיור 1.

כדי שהתצוגות המקדימות של הווידג'טים עם תצוגות אוסף יוצגו בצורה תקינה בכלי לבחירת הווידג'טים, מומלץ לשמור קובץ פריסה נפרד שמוגדר רק לתצוגה המקדימה. קובץ הפריסה הנפרד הזה צריך לכלול את הפרטים הבאים:

  • פריסת הווידג'ט בפועל.
  • תצוגת אוסף של פלייסהולדרים עם פריטים מזויפים. לדוגמה, אפשר לחקות ListView על ידי הוספת placeholder‏ LinearLayout עם כמה פריטים מזויפים של רשימה.

כדי להמחיש דוגמה ל-ListView, מתחילים בקובץ פריסה נפרד:

// res/layout/widget_preview.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
   android:layout_width="match_parent"
   android:layout_height="wrap_content"
   android:background="@drawable/widget_background"
   android:orientation="vertical">

    // Include the actual widget layout that contains ListView.
    <include
        layout="@layout/widget_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content" />

    // The number of fake items you include depends on the values you provide
    // for minHeight or targetCellHeight in the AppWidgetProviderInfo
    // definition.

    <TextView android:text="@string/fake_item1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

    <TextView android:text="@string/fake_item2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginVertical="?attr/appWidgetInternalPadding" />

</LinearLayout>

כשמספקים את מאפיין previewLayout של המטא-נתונים AppWidgetProviderInfo, צריך לציין את קובץ פריסת התצוגה המקדימה. עדיין צריך לציין את פריסת הווידג'ט בפועל במאפיין initialLayout ולהשתמש בפריסת הווידג'ט בפועל כשיוצרים RemoteViews בזמן ריצה.

<appwidget-provider
    previewLayout="@layout/widget_previe"
    initialLayout="@layout/widget_view" />

פריטים מורכבים ברשימה

בדוגמה שבקטע הקודם מוצגים פריטים מזויפים ברשימה, כי הפריטים ברשימה הם אובייקטים מסוג TextView. יכול להיות שיהיה יותר מורכב לספק פריטים מזויפים אם הפריטים הם פריסות מורכבות.

נניח שיש פריט ברשימה שמוגדר ב-widget_list_item.xml ומורכב משני אובייקטים מסוג TextView:

<LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
        android:layout_width="match_parent"
        android:layout_height="wrap_content">

    <TextView android:id="@id/title"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_title" />

    <TextView android:id="@id/content"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="@string/fake_content" />
</LinearLayout>

כדי לספק פריטים מזויפים ברשימה, אפשר לכלול את הפריסה כמה פעמים, אבל במקרה כזה כל פריט ברשימה יהיה זהה. כדי לספק פריטים ייחודיים לרשימה, פועלים לפי השלבים הבאים:

  1. יוצרים קבוצת מאפיינים לערכי הטקסט:

    <resources>
        <attr name="widgetTitle" format="string" />
        <attr name="widgetContent" format="string" />
    </resources>
    
  2. משתמשים במאפיינים האלה כדי להגדיר את הטקסט:

    <LinearLayout  xmlns:android="http://schemas.android.com/apk/res/android"
            android:layout_width="match_parent"
            android:layout_height="wrap_content">
    
        <TextView android:id="@id/title"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetTitle" />
    
        <TextView android:id="@id/content"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="?widgetContent" />
    </LinearLayout>
    
  3. יוצרים כמה סגנונות שצריך לתצוגה המקדימה. מגדירים מחדש את הערכים בכל סגנון:

    <resources>
    
        <style name="Theme.Widget.ListItem">
            <item name="widgetTitle"></item>
            <item name="widgetContent"></item>
        </style>
        <style name="Theme.Widget.ListItem.Preview1">
            <item name="widgetTitle">Fake Title 1</item>
            <item name="widgetContent">Fake content 1</item>
        </style>
        <style name="Theme.Widget.ListItem.Preview2">
            <item name="widgetTitle">Fake title 2</item>
            <item name="widgetContent">Fake content 2</item>
        </style>
    
    </resources>
    
  4. החלת הסגנונות על הפריטים המזויפים בפריסת התצוגה המקדימה:

    <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
       android:layout_width="match_parent"
       android:layout_height="wrap_content" ...>
    
        <include layout="@layout/widget_view" ... />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview1" />
    
        <include layout="@layout/widget_list_item"
            android:theme="@style/Theme.Widget.ListItem.Preview2" />
    
    </LinearLayout>