manifes, metadata
Bagian berikut menjelaskan cara membuat widget aplikasi dasar dengan Glance.
Mendeklarasikan AppWidget dalam Manifes
Setelah menyelesaikan langkah-langkah penyiapan, deklarasikan AppWidget dan metadatanya di aplikasi Anda.
Perluas penerima
AppWidgetdariGlanceAppWidgetReceiver:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
Daftarkan penyedia widget aplikasi di file
AndroidManifest.xmldan file metadata terkait:<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>
Tambahkan metadata AppWidgetProviderInfo
Selanjutnya, ikuti panduan Membuat widget untuk membuat dan menentukan info widget aplikasi di file @xml/my_app_widget_info.
Satu-satunya perbedaan untuk Glance adalah tidak ada XML initialLayout, tetapi Anda
harus menentukannya. Anda dapat menggunakan tata letak pemuatan standar yang disediakan di
library:
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialLayout="@layout/glance_default_loading_layout">
</appwidget-provider>
Mendeklarasikan XML AppWidgetProviderInfo
Objek AppWidgetProviderInfo menentukan kualitas penting widget Anda. Tentukan AppWidgetProviderInfo di file resource metadata XML
(res/xml/my_app_widget_info.xml) dalam elemen <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>
Atribut ukuran widget
Layar utama default memosisikan widget di jendelanya berdasarkan petak sel yang memiliki tinggi dan lebar yang ditentukan. Sebagian besar layar utama hanya mengizinkan widget mengambil ukuran yang merupakan kelipatan bilangan bulat dari sel petak—misalnya, dua sel secara horizontal dan tiga sel secara vertikal.
Atribut ukuran widget memungkinkan Anda menentukan ukuran default untuk widget dan memberikan batas bawah dan atas pada ukuran widget. Dalam konteks ini, ukuran default widget adalah ukuran yang dimiliki widget saat pertama kali ditambahkan ke layar utama.
Tabel berikut menjelaskan atribut <appwidget-provider> yang berkaitan dengan ukuran widget:
| Atribut dan deskripsi | |
|---|---|
targetCellWidth dan
targetCellHeight (Android 12),
minWidth dan minHeight |
targetCellWidth dan
targetCellHeight, serta minWidth dan
minHeight—agar aplikasi Anda dapat melakukan penggantian ke penggunaan
minWidth dan minHeight jika perangkat pengguna
tidak mendukung targetCellWidth dan
targetCellHeight. Jika didukung, atribut
targetCellWidth dan targetCellHeight
lebih diutamakan daripada atribut minWidth dan minHeight.
|
minResizeWidth dan
minResizeHeight |
Menentukan ukuran minimum absolut widget. Nilai ini menentukan
ukuran yang akan menjadikan widget tidak terbaca atau tidak dapat dipakai jika berada di bawahnya. Penggunaan
atribut ini memungkinkan pengguna mengubah ukuran widget ke ukuran yang lebih kecil
daripada ukuran widget default. Atribut minResizeWidth diabaikan jika lebih besar dari minWidth atau jika pengubahan ukuran secara horizontal tidak diaktifkan. Lihat
resizeMode. Demikian pula, atribut
minResizeHeight diabaikan jika lebih besar dari
minHeight atau jika pengubahan ukuran secara vertikal tidak diaktifkan. |
maxResizeWidth dan
maxResizeHeight |
Tentukan ukuran maksimum widget yang direkomendasikan. Jika nilai bukan
kelipatan dimensi sel petak, nilai akan dibulatkan ke atas ke
ukuran sel terdekat. Atribut maxResizeWidth diabaikan jika
lebih kecil dari minWidth atau jika pengubahan ukuran horizontal tidak
diaktifkan. Lihat resizeMode. Demikian pula,
atribut maxResizeHeight diabaikan jika lebih kecil
daripada minHeight atau jika pengubahan ukuran vertikal tidak diaktifkan.
Diperkenalkan di Android 12. |
resizeMode |
Menentukan aturan yang menjadikan ukuran widget dapat diubah. Anda dapat menggunakan atribut ini untuk membuat widget layar utama dapat diubah ukurannya secara horizontal, vertikal, atau pada kedua sumbu. Pengguna menyentuh lama widget untuk menampilkan tuas pengubah ukuran,
lalu menarik tuas horizontal atau vertikal untuk mengubah ukurannya pada
petak tata letak. Nilai untuk atribut resizeMode mencakup
horizontal, vertical, dan none. Untuk
mendeklarasikan widget dapat diubah ukurannya secara horizontal dan vertikal, gunakan
horizontal|vertical. |
Contoh
Untuk menggambarkan pengaruh atribut dalam tabel sebelumnya terhadap ukuran widget, asumsikan spesifikasi berikut:
- Sel petak memiliki lebar 30 dp dan tinggi 50 dp.
- Spesifikasi atribut berikut diberikan:
<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" />
Mulai dengan Android 12:
Gunakan atribut targetCellWidth dan targetCellHeight sebagai ukuran default
widget.
Ukuran widget adalah 2x2 secara default. Widget dapat diubah ukurannya menjadi 2x1 atau hingga 4x3.
Android 11 dan yang lebih lama:
Gunakan atribut minWidth dan minHeight untuk menghitung ukuran default
widget.
Lebar default = Math.ceil(80 / 30) = 3
Tinggi default = Math.ceil(80 / 50) = 2
Ukuran widget adalah 3x2 secara default. Widget dapat diubah ukurannya menjadi 2x1 atau hingga layar penuh.
Atribut widget tambahan
Tabel berikut menjelaskan atribut <appwidget-provider> yang berkaitan dengan kualitas selain ukuran widget.
| Atribut dan deskripsi | |
|---|---|
updatePeriodMillis |
Menentukan seberapa sering framework widget meminta update dari
GlanceAppWidgetReceiver dengan memanggil metode callback
onUpdate(). Sebaiknya update sesering mungkin, tetapi tidak lebih dari sekali dalam satu jam, untuk menghemat baterai.
Untuk mengetahui detailnya, lihat bagian Kapan harus memperbarui widget di Pengelolaan status sekilas. |
initialLayout |
Mengarah ke resource tata letak yang menentukan tata letak pemuatan widget sebelum komposisi UI Glance dirender. Anda dapat menggunakan tata letak pemuatan standar yang disediakan di library: @layout/glance_default_loading_layout. |
configure |
Menentukan aktivitas konfigurasi yang diluncurkan saat pengguna menambahkan widget. Lihat bagian Menerapkan Aktivitas konfigurasi widget di halaman ini. |
description |
Menentukan deskripsi untuk alat pilih widget yang akan ditampilkan untuk widget Anda. Diperkenalkan di Android 12. |
previewLayout (Android 12)
dan previewImage (Android 11 dan yang lebih lama) |
|
autoAdvanceViewId |
Menentukan ID tampilan sub-tampilan widget yang dimajukan secara otomatis oleh host widget. |
widgetCategory |
Mendeklarasikan apakah widget Anda dapat ditampilkan di layar utama
(home_screen), layar kunci (keyguard), atau keduanya. Untuk Android 5.0 dan yang lebih tinggi, hanya home_screen yang valid. |
widgetFeatures |
Mendeklarasikan fitur yang didukung oleh widget. Misalnya, jika konfigurasi widget Anda bersifat opsional, tentukan configuration_optional dan reconfigurable. |
Tentukan GlanceAppWidget
Buat class baru yang diperluas dari
GlanceAppWidgetdan mengganti metodeprovideGlance. Ini adalah metode tempat Anda dapat memuat data yang diperlukan untuk merender widget: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") } } }
Buat instance di
glanceAppWidgetdiGlanceAppWidgetReceiverAnda:class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { // Let MyAppWidgetReceiver know which GlanceAppWidget to use override val glanceAppWidget: GlanceAppWidget = MyAppWidget() }
Anda kini telah mengonfigurasi AppWidget menggunakan Glance.
Menggunakan class AppWidgetProvider untuk menangani siaran widget
Widget koordinat GlanceAppWidgetReceiver menyiarkan dan memperbarui status platform dengan memperluas AppWidgetProvider yang mendasarinya. Widget ini menerima
peristiwa platform saat widget Anda diupdate, dihapus, diaktifkan, atau dinonaktifkan,
dan menerjemahkannya ke dalam permintaan siklus proses Compose.
Mendeklarasikan widget dalam manifes
Deklarasikan subclass class GlanceAppWidgetReceiver Anda sebagai penerima siaran dalam
file AndroidManifest.xml Anda:
<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>
Elemen <receiver> memerlukan atribut android:name, yang menentukan
class penerima. Penerima harus menerima tindakan siaran ACTION_APPWIDGET_UPDATE
di dalam <intent-filter>.
Elemen <meta-data> harus mengidentifikasi namanya sebagai
android.appwidget.provider, dan atribut android:resource harus mengarah ke
resource metadata XML AppWidgetProviderInfo Anda (@xml/my_app_widget_info).
Mengimplementasikan class AppWidgetProvider
Di Glance, Anda memperluas GlanceAppWidgetReceiver, bukan
AppWidgetProvider secara langsung. Terapkan dengan menautkan penerima ke instance
GlanceAppWidget Anda. Callback utama yang tersedia di
GlanceAppWidgetReceiver beroperasi sebagai berikut:
onUpdate(): Secara otomatis diganti oleh Glance untuk mengeksekusi update komposisi. Jika Anda menggantionUpdatesecara manual, Anda harus memanggilsuper.onUpdateuntuk memungkinkan Glance meluncurkan thread komposisi dengan berhasil.onAppWidgetOptionsChanged(): Dipanggil saat widget pertama kali ditempatkan atau diubah ukurannya. Opsi baca sekilas menggabungkan item di balik layar sehingga tata letak Anda menyesuaikan dengan lancar berdasarkan dimensi runtime.onDeleted(Context, IntArray): Dipanggil setiap kali instance widget tertentu dihapus oleh pengguna.onEnabled(Context): Dipicu saat instance pertama widget Anda berhasil dibuat. Sangat baik untuk menjalankan migrasi global.onDisabled(Context): Dipanggil saat instance aktif terakhir penyedia dihapus.onReceive(Context, Intent): Menyadap setiap siaran platform sebelum metode callback tertentu. Anda harus memastikan bahwa logika penerima kustom yang Anda tulis memanggilsuper.onReceive(context, intent)dan tidak boleh memanggilgoAsyncsendiri karena Glance otomatis merutekan pekerjaan secara asinkron.
Menerima intent siaran widget
Di balik layar, GlanceAppWidgetReceiver memfilter dan menangani intent siaran widget platform dasar berikut:
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
Membuat UI
Cuplikan berikut menunjukkan cara membuat 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>() ) } } } }
Contoh kode sebelumnya melakukan hal berikut:
- Di
Columntingkat atas, item ditempatkan secara vertikal satu demi satu. Columnmemperluas ukurannya agar sesuai dengan ruang yang tersedia (melaluiGlanceModifierdan menyelaraskan kontennya ke atas (verticalAlignment) serta memusatkannya secara horizontal (horizontalAlignment).- Konten
Columnditentukan menggunakan lambda. Urutannya penting.- Item pertama di
Columnadalah komponenTextdengan12.dppadding. - Item kedua adalah
Row, tempat item ditempatkan secara horizontal satu per satu, dengan duaButtonsyang dipusatkan secara horizontal (horizontalAlignment). Tampilan akhir bergantung pada ruang yang tersedia. Gambar berikut adalah contoh tampilannya:
- Item pertama di
Anda dapat mengubah nilai perataan atau menerapkan nilai pengubah yang berbeda (seperti padding) untuk mengubah penempatan dan ukuran komponen. Lihat dokumentasi referensi untuk mengetahui daftar lengkap komponen, parameter, dan pengubah yang tersedia untuk setiap class.
Menerapkan sudut bulat
Android 12 memperkenalkan parameter sistem untuk menyesuaikan radius sudut widget aplikasi Anda secara dinamis:
system_app_widget_background_radius: Menentukan radius sudut penampung latar belakang widget (tidak boleh lebih besar dari 28 dp).- Radius dalam: Untuk mencegah pemangkasan konten, hitung radius proporsional
untuk konten dalam berdasarkan garis batas latar belakang sistem:
systemRadiusValue - widgetPadding
Di Glance, Anda dapat menerapkan properti ukuran radius sudut secara dinamis dalam
komposisi menggunakan
GlanceModifier.cornerRadius(android.R.dimen.system_app_widget_background_radius).
Untuk kompatibilitas mundur di perangkat yang menjalankan Android 11 (API level 30) atau yang lebih rendah, terapkan atribut kustom dan penggantian resource tema kustom:
/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>