با Glance یک ویجت برنامه ایجاد کنید

مانیفست، فراداده

بخش‌های زیر نحوه ایجاد یک ویجت برنامه اولیه با Glance را شرح می‌دهند.

اعلان AppWidget در Manifest

پس از تکمیل مراحل راه‌اندازی ، AppWidget و متادیتای آن را در برنامه خود تعریف کنید.

  1. گیرنده AppWidget را از GlanceAppWidgetReceiver بسط دهید:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
        override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget")
    }

  2. ارائه دهنده ویجت برنامه را در فایل 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 این است که initialLayout XML وجود ندارد، اما باید یکی تعریف کنید. می‌توانید از طرح بارگذاری از پیش تعریف شده ارائه شده در کتابخانه استفاده کنید:

<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 (اندروید ۱۲)، minWidth و minHeight
  • از اندروید ۱۲ به بعد، ویژگی‌های targetCellWidth و targetCellHeight اندازه پیش‌فرض ویجت را بر حسب سلول‌های شبکه‌ای مشخص می‌کنند. این ویژگی‌ها در اندروید ۱۱ و پایین‌تر نادیده گرفته می‌شوند و اگر صفحه اصلی از طرح‌بندی مبتنی بر شبکه پشتیبانی نکند، می‌توان آن‌ها را نادیده گرفت.
  • ویژگی‌های minWidth و minHeight اندازه پیش‌فرض ویجت را بر حسب dp مشخص می‌کنند. اگر مقادیر مربوط به حداقل عرض یا ارتفاع ویجت با ابعاد سلول‌ها مطابقت نداشته باشند، مقادیر به نزدیکترین اندازه سلول گرد می‌شوند.
توصیه می‌کنیم هر دو مجموعه از ویژگی‌ها targetCellWidth و targetCellHeight و minWidth و minHeight - را مشخص کنید تا در صورت عدم پشتیبانی دستگاه کاربر targetCellWidth و targetCellHeight ، برنامه شما بتواند به استفاده minWidth و minHeight بازگردد. در صورت پشتیبانی، ویژگی‌های targetCellWidth و targetCellHeight بر ویژگی‌های minWidth و minHeight اولویت دارند.
minResizeWidth و minResizeHeight حداقل اندازه مطلق ویجت را مشخص کنید. این مقادیر، اندازه‌ای را مشخص می‌کنند که ویجت در آن ناخوانا یا غیرقابل استفاده است. استفاده از این ویژگی‌ها به کاربر اجازه می‌دهد تا ویجت را به اندازه‌ای کوچکتر از اندازه پیش‌فرض ویجت تغییر اندازه دهد. ویژگی minResizeWidth اگر بزرگتر از minWidth باشد یا تغییر اندازه افقی فعال نباشد، نادیده گرفته می‌شود. به resizeMode مراجعه کنید. به همین ترتیب، ویژگی minResizeHeight اگر بزرگتر از minHeight باشد یا تغییر اندازه عمودی فعال نباشد، نادیده گرفته می‌شود.
maxResizeWidth و maxResizeHeight حداکثر اندازه توصیه‌شده برای ویجت را مشخص کنید. اگر مقادیر مضربی از ابعاد سلول‌های شبکه نباشند، به نزدیکترین اندازه سلول گرد می‌شوند. اگر ویژگی maxResizeWidth کوچکتر از minWidth باشد یا تغییر اندازه افقی فعال نباشد، نادیده گرفته می‌شود. به resizeMode مراجعه کنید. به همین ترتیب، اگر ویژگی maxResizeHeight کوچکتر از minHeight باشد یا تغییر اندازه عمودی فعال نباشد، نادیده گرفته می‌شود. در اندروید ۱۲ معرفی شده است.
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" />

شروع با اندروید ۱۲:

از ویژگی‌های targetCellWidth و targetCellHeight به عنوان اندازه پیش‌فرض ویجت استفاده کنید.

اندازه ویجت به طور پیش‌فرض ۲x۲ است. می‌توان آن را به ۲x۱ یا تا ۴x۳ تغییر داد.

اندروید ۱۱ و پایین‌تر:

از ویژگی‌های minWidth و minHeight برای محاسبه اندازه پیش‌فرض ویجت استفاده کنید.

عرض پیش‌فرض = Math.ceil(80 / 30) = 3

ارتفاع پیش‌فرض = Math.ceil(80 / 50) = 2

اندازه ویجت به طور پیش‌فرض ۳x۲ است. می‌توان آن را به ۲x۱ یا تا تمام صفحه تغییر اندازه داد.

ویژگی‌های ویجت اضافی

جدول زیر ویژگی‌های <appwidget-provider> مربوط به ویژگی‌هایی غیر از اندازه ویجت را شرح می‌دهد.

ویژگی‌ها و توضیحات
updatePeriodMillis تعریف می‌کند که فریم‌ورک ویجت با فراخوانی متد onUpdate() چند وقت یکبار درخواست به‌روزرسانی از GlanceAppWidgetReceiver را می‌دهد. توصیه می‌کنیم برای صرفه‌جویی در مصرف باتری، به‌روزرسانی را تا حد امکان به ندرت - حداکثر هر یک ساعت - انجام دهید. برای جزئیات بیشتر، به بخش «چه زمانی ویجت‌ها را به‌روزرسانی کنیم» در مدیریت وضعیت Glance مراجعه کنید.
initialLayout به منبع طرح‌بندی اشاره می‌کند که طرح‌بندی بارگذاری ویجت را قبل از رندر شدن کامپوزیشن‌های Glance UI تعریف می‌کند. می‌توانید از طرح‌بندی بارگذاری از پیش تعریف‌شده‌ی ارائه شده در کتابخانه استفاده کنید: @layout/glance_default_loading_layout .
configure فعالیت پیکربندی را تعریف می‌کند که هنگام افزودن ویجت توسط کاربر اجرا می‌شود. به بخش «فعالیت پیکربندی ویجت» در این صفحه مراجعه کنید.
description توضیحی را برای انتخابگر ویجت جهت نمایش ویجت شما مشخص می‌کند. معرفی شده در اندروید ۱۲.
previewLayout (اندروید ۱۲) و previewImage (اندروید ۱۱ و پایین‌تر)
  • از اندروید ۱۲ به بعد، ویژگی previewLayout یک پیش‌نمایش مقیاس‌پذیر را مشخص می‌کند که شما آن را به عنوان یک طرح‌بندی XML که با اندازه پیش‌فرض ویجت تنظیم شده است، ارائه می‌دهید. در حالت ایده‌آل، این به یک نگاشت XML استاتیک مطابق با طرح‌بندی طراحی شما اشاره دارد.
  • در اندروید ۱۱ یا پایین‌تر، ویژگی previewImage یک تصویر ثابت قابل ترسیم از ظاهر ویجت را مشخص می‌کند که در انتخابگر ویجت نمایش داده می‌شود.
توصیه می‌کنیم هر دو را مشخص کنید تا برنامه شما به راحتی روی پلتفرم‌های قدیمی‌تر هم اجرا شود. برای پلتفرم‌های جدیدتر (اندروید ۱۵+)، می‌توانید پیش‌نمایش‌های زنده تولید شده را در کاتلین با استفاده از `GlanceAppWidget.providePreview` تعریف کنید. به راهنمای پیش‌نمایش‌های تولید شده مراجعه کنید.
autoAdvanceViewId شناسه نمای زیرنمای ویجت را که توسط میزبان ویجت به صورت خودکار ارتقا داده می‌شود، مشخص می‌کند.
widgetCategory مشخص می‌کند که آیا ویجت شما می‌تواند در صفحه اصلی ( home_screen )، صفحه قفل ( keyguard ) یا هر دو نمایش داده شود یا خیر. برای اندروید ۵.۰ و بالاتر، فقط home_screen معتبر است.
widgetFeatures ویژگی‌های پشتیبانی‌شده توسط ویجت را اعلام می‌کند. برای مثال، اگر پیکربندی ویجت شما اختیاری است، هم configuration_optional و هم reconfigurable را مشخص کنید.

تعریف GlanceAppWidget

  1. یک کلاس جدید ایجاد کنید که از GlanceAppWidget ارث‌بری کند و متد provideGlance override کند. این متدی است که می‌توانید داده‌های مورد نیاز برای رندر ویجت خود را در آن بارگذاری کنید:

    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")
            }
        }
    }

  2. آن را در glanceAppWidget روی GlanceAppWidgetReceiver خود نمونه‌سازی کنید:

    class MyAppWidgetReceiver : GlanceAppWidgetReceiver() {
    
        // Let MyAppWidgetReceiver know which GlanceAppWidget to use
        override val glanceAppWidget: GlanceAppWidget = MyAppWidget()
    }

اکنون با استفاده از Glance یک AppWidget پیکربندی کرده‌اید.

از کلاس AppWidgetProvider برای مدیریت پخش ویجت‌ها استفاده کنید

GlanceAppWidgetReceiver با بسط دادن AppWidgetProvider زیرین، پخش‌های ویجت و به‌روزرسانی‌های وضعیت پلتفرم را هماهنگ می‌کند. این GlanceAppWidgetReceiver رویدادهای پلتفرم را هنگام به‌روزرسانی، حذف، فعال یا غیرفعال شدن ویجت شما دریافت کرده و آنها را به درخواست‌های چرخه عمر 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 ) اشاره کند.

کلاس AppWidgetProvider را پیاده‌سازی کنید

در Glance، شما به جای AppWidgetProvider مستقیماً از GlanceAppWidgetReceiver ارث بری می‌کنید. آن را با پیوند دادن receiver خود به نمونه 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 اهداف پخش ویجت پلتفرم بنیادی زیر را فیلتر و مدیریت می‌کند:

ایجاد رابط کاربری

قطعه کد زیر نحوه ایجاد رابط کاربری (UI) را نشان می‌دهد:

/* 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 با استفاده از لامبدا تعریف می‌شود. ترتیب مهم است.
    • اولین آیتم در Column یک کامپوننت Text با 12.dp پدینگ است.
    • مورد دوم یک ردیف ( Row ) است که در آن موارد به صورت افقی یکی پس از دیگری قرار می‌گیرند و دو Buttons به صورت افقی در مرکز قرار می‌گیرند ( horizontalAlignment ). نمایش نهایی به فضای موجود بستگی دارد. تصویر زیر نمونه‌ای از آن است:
ویجت_مقصد
شکل ۱. یک رابط کاربری نمونه.

شما می‌توانید مقادیر ترازبندی را تغییر دهید یا مقادیر اصلاح‌کننده‌ی متفاوتی (مانند padding) را برای تغییر محل قرارگیری و اندازه‌ی اجزا اعمال کنید. برای مشاهده‌ی لیست کامل اجزا، پارامترها و اصلاح‌کننده‌های موجود برای هر کلاس، به مستندات مرجع مراجعه کنید.

پیاده‌سازی گوشه‌های گرد

اندروید ۱۲ پارامترهای سیستمی را برای سفارشی‌سازی پویای شعاع گوشه‌های ویجت‌های برنامه شما معرفی می‌کند:

  • system_app_widget_background_radius : شعاع گوشه‌ی ظرف پس‌زمینه‌ی ویجت را مشخص می‌کند (هرگز بزرگتر از ۲۸ dp نباشد).
  • شعاع داخلی: برای جلوگیری از برش محتوا، شعاع متناسبی را برای محتوای داخلی خود بر اساس طرح کلی پس‌زمینه سیستم محاسبه کنید: systemRadiusValue - widgetPadding

در Glance، می‌توانید ویژگی‌های اندازه‌گیری شعاع گوشه را به صورت پویا در ترکیب‌بندی با استفاده از GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius) اعمال کنید.

برای سازگاری معکوس در دستگاه‌هایی که اندروید ۱۱ (سطح 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>