توضِّح الأقسام التالية كيفية إنشاء تطبيق مصغّر أساسي باستخدام 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 (الإصدار 12 من نظام التشغيل Android)، و
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 أو إذا لم يكن تغيير الحجم عموديًا مفعّلاً.
تم طرح هذه السمة في الإصدار 12 من نظام التشغيل Android. |
resizeMode |
تحديد القواعد التي يمكن بموجبها تغيير حجم التطبيق المصغّر يمكنك استخدام هذه
السمة لجعل التطبيقات المصغّرة على الشاشة الرئيسية قابلة لتغيير الحجم أفقيًا أو عموديًا
أو على كلا المحورَين. ينقر المستخدِمون مع الاستمرار على تطبيق مصغّر لعرض مقابض تغيير الحجم،
ثم يسحبون المقابض الأفقية أو العمودية لتغيير حجمه على
شبكة التنسيق. تشمل قيم السمة resizeMode كلاً من
horizontal وvertical وnone. للإعلان عن تطبيق مصغّر قابل لتغيير الحجم أفقيًا وعموديًا، استخدِم
horizontal|vertical. |
مثال
لتوضيح كيفية تأثير السمات في الجدول السابق على تغيير حجم التطبيق المصغّر، لنفترض المواصفات التالية:
- عرض خلية الشبكة 30 dp وارتفاعها 50 dp.
- تم تقديم مواصفات السمة التالية:
<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" />
بدءًا من الإصدار 12 من نظام التشغيل Android:
استخدِم السمتَين targetCellWidth وtargetCellHeight كحجم تلقائي للتطبيق المصغّر.
حجم التطبيق المصغّر هو 2×2 تلقائيًا. يمكن تغيير حجم التطبيق المصغّر إلى 2×1 أو 4×3.
الإصدار 11 من نظام التشغيل Android والإصدارات الأقدم:
استخدِم السمتَين minWidth وminHeight لاحتساب الحجم التلقائي للتطبيق المصغّر.
العرض التلقائي = Math.ceil(80 / 30) = 3
الارتفاع التلقائي = Math.ceil(80 / 50) = 2
حجم التطبيق المصغّر هو 3×2 تلقائيًا. يمكن تغيير حجم التطبيق المصغّر إلى 2×1 أو ملء الشاشة.
سمات التطبيق المصغّر الإضافية
يوضِّح الجدول التالي سمات <appwidget-provider> المتعلّقة
بالخصائص الأخرى غير تغيير حجم التطبيق المصغّر.
| السمات والوصف | |
|---|---|
updatePeriodMillis |
تحديد عدد المرات التي يطلب فيها إطار عمل التطبيق المصغّر تحديثًا من الـ
GlanceAppWidgetReceiver من خلال استدعاء طريقة رد الاتصال onUpdate() ننصحك بإجراء التحديث بأقل قدر ممكن من التكرار، أي مرة واحدة في الساعة على الأكثر، للحفاظ على البطارية.
لمزيد من التفاصيل، راجِع قسم وقت تحديث التطبيقات المصغّرة في إدارة حالة Glance. |
initialLayout |
يشير إلى مصدر التنسيق الذي يحدّد تنسيق التحميل الخاص بالتطبيق المصغّر قبل عرض تركيبات واجهة مستخدم Glance. يمكنك استخدام تنسيق التحميل المحدّد مسبقًا والمتاح في المكتبة: @layout/glance_default_loading_layout. |
configure |
تحديد نشاط الإعداد الذي يتم تشغيله عندما يضيف المستخدِم التطبيق المصغّر راجِع قسم تنفيذ نشاط إعداد تطبيق مصغّر في هذه الصفحة. |
description |
تحديد الوصف الذي يعرضه منتقي التطبيقات المصغّرة لتطبيقك المصغّر تم طرح هذه السمة في الإصدار 12 من نظام التشغيل Android. |
previewLayout (الإصدار 12 من نظام التشغيل Android)
وpreviewImage (الإصدار 11 من نظام التشغيل Android والإصدارات الأقدم) |
|
autoAdvanceViewId |
تحديد معرّف العرض للعرض الفرعي للتطبيق المصغّر الذي يتم تقدّمه تلقائيًا من قِبل مضيف التطبيق المصغّر |
widgetCategory |
تحديد ما إذا كان يمكن عرض تطبيقك المصغّر على الشاشة الرئيسية
(home_screen) أو شاشة القفل (keyguard) أو كلتيهما بالنسبة إلى الإصدار 5.0 من نظام التشغيل Android والإصدارات الأحدث، تكون 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="ExampleAppWidgetReceiver"
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(): يتم استدعاؤها عند وضع التطبيق المصغّر لأول مرة أو تغيير حجمه. يقرأ Glance عناصر حزمة الخيارات تحت الغطاء، لذا يتم تعديل التنسيق بسلاسة استنادًا إلى الأبعاد في وقت التشغيل.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باستخدام تعبير لامدا. الترتيب مهم.
يمكنك تغيير قيم المحاذاة أو تطبيق قيم معدِّل مختلفة (مثل مساحة الترك) لتغيير موضع المكوّنات وحجمها. راجِع المستندات المرجعية للحصول على قائمة كاملة بالمكوّنات والمعلّمات والمعدِّلات المتاحة لكل فئة.
تنفيذ الزوايا المستديرة
يطرح الإصدار 12 من نظام التشغيل Android معلّمات نظام لتخصيص أنصاف أقطار زوايا التطبيقات المصغّرة ديناميكيًا:
system_app_widget_background_radius: تحديد نصف قطر زاوية حاوية خلفية التطبيق المصغّر (لا يكون أكبر من 28 dp أبدًا)- نصف القطر الداخلي: لمنع اقتصاص المحتوى، عليك احتساب نصف قطر متناسب للمحتوى الداخلي استنادًا إلى المخطط التفصيلي لخلفية النظام:
systemRadiusValue - widgetPadding
في Glance، يمكنك تطبيق خصائص تغيير حجم نصف القطر ديناميكيًا في التركيب باستخدام GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
لضمان التوافق مع الأنظمة القديمة على الأجهزة التي تعمل بالإصدار 11 من نظام التشغيل Android (مستوى واجهة برمجة التطبيقات 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>