ส่วนต่อไปนี้จะอธิบายวิธีสร้าง App Widget พื้นฐานด้วย Glance
ประกาศ AppWidget ในไฟล์ Manifest
หลังจากทำตามขั้นตอนการตั้งค่าแล้ว ให้ประกาศ AppWidget และ
ข้อมูลเมตาในแอป
ขยายตัวรับ
AppWidgetจากGlanceAppWidgetReceiverดังนี้class MyAppWidgetReceiver : GlanceAppWidgetReceiver() { override val glanceAppWidget: GlanceAppWidget = TODO("Create GlanceAppWidget") }
ลงทะเบียนผู้ให้บริการ App Widget ในไฟล์
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
จากนั้นทำตามคู่มือ สร้างวิดเจ็ต เพื่อสร้างและกำหนดข้อมูล App
Widget ในไฟล์ @xml/my_app_widget_info
ความแตกต่างเพียงอย่างเดียวของ Glance คือไม่มี XML 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>
แอตทริบิวต์การปรับขนาดวิดเจ็ต
ตำแหน่งเริ่มต้นของวิดเจ็ตในหน้าจอหลักจะอยู่ในหน้าต่างของวิดเจ็ตโดยอิงตามตารางกริดของเซลล์ที่มีความสูงและความกว้างที่กำหนด หน้าจอหลักส่วนใหญ่จะอนุญาตให้วิดเจ็ตมีขนาดเป็นจำนวนเต็มเท่าของเซลล์กริด เช่น 2 เซลล์ในแนวนอนและ 3 เซลล์ในแนวตั้ง
แอตทริบิวต์การปรับขนาดวิดเจ็ตช่วยให้คุณระบุขนาดเริ่มต้นของวิดเจ็ต รวมถึงกำหนดขอบเขตล่างและขอบเขตบนของขนาดวิดเจ็ตได้ ในบริบทนี้ ขนาดเริ่มต้นของวิดเจ็ตคือขนาดที่วิดเจ็ตมีเมื่อเพิ่มลงในหน้าจอหลักเป็นครั้งแรก
ตารางต่อไปนี้อธิบายแอตทริบิวต์ <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 |
ระบุกฎที่ใช้ปรับขนาดวิดเจ็ต คุณสามารถใช้แอตทริบิวต์นี้เพื่อทำให้วิดเจ็ตหน้าจอหลักปรับขนาดได้ในแนวนอน แนวตั้ง หรือทั้ง 2 แกน ผู้ใช้แตะค้างที่วิดเจ็ตเพื่อแสดงแฮนเดิลการปรับขนาด
จากนั้นลากแฮนเดิลแนวนอนหรือแนวตั้งเพื่อเปลี่ยนขนาดใน
กริดเลย์เอาต์ ค่าสำหรับแอตทริบิวต์ 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" />
ตั้งแต่ 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 โดยการเรียกใช้เมธอด Callback onUpdate() เราขอแนะนำให้อัปเดตให้น้อยที่สุดเท่าที่จะทำได้
โดยไม่เกิน 1 ครั้งต่อชั่วโมง เพื่อประหยัดแบตเตอรี่
ดูรายละเอียดได้ที่ส่วนเวลาที่ควรจะอัปเดตวิดเจ็ตในการจัดการสถานะ Glance |
initialLayout |
ชี้ไปยังทรัพยากรเลย์เอาต์ที่กำหนดเลย์เอาต์การโหลดของวิดเจ็ตก่อนที่องค์ประกอบ UI ของ Glance จะแสดงผล คุณสามารถใช้เลย์เอาต์การโหลดที่กำหนดไว้ล่วงหน้าซึ่งมีให้ในไลบรารีได้ดังนี้ @layout/glance_default_loading_layout |
configure |
กำหนดกิจกรรมการกำหนดค่าที่จะเปิดตัวเมื่อผู้ใช้เพิ่มวิดเจ็ต ดูคู่มือใช้กิจกรรมการกำหนดค่า |
description |
ระบุคำอธิบายสำหรับเครื่องมือเลือกวิดเจ็ตที่จะแสดงสำหรับวิดเจ็ต เปิดตัวใน Android 12 |
previewLayout (Android 12)
และ previewImage (Android 11 และต่ำกว่า) |
|
autoAdvanceViewId |
ระบุรหัสมุมมองของมุมมองย่อยของวิดเจ็ตที่โฮสต์ของวิดเจ็ตจะเลื่อนไปข้างหน้าโดยอัตโนมัติ |
widgetCategory |
ประกาศว่าวิดเจ็ตจะแสดงในหน้าจอหลัก
(home_screen), หน้าจอล็อก (keyguard) หรือทั้ง 2 อย่าง สำหรับ 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
ประกาศวิดเจ็ตในไฟล์ Manifest
ประกาศคลาสย่อย 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(): เรียกใช้เมื่อวางหรือปรับขนาดวิดเจ็ตเป็นครั้งแรก Glance จะอ่านรายการชุดตัวเลือกเบื้องหลังเพื่อให้เลย์เอาต์ปรับเปลี่ยนได้อย่างราบรื่นตามขนาดรันไทม์onDeleted(Context, IntArray): เรียกใช้เมื่อผู้ใช้ลบอินสแตนซ์วิดเจ็ตที่เฉพาะเจาะจงonEnabled(Context): ทริกเกอร์เมื่อสร้างอินสแตนซ์แรกของวิดเจ็ตได้สำเร็จ เหมาะสำหรับการเรียกใช้การย้ายข้อมูลส่วนกลางonDisabled(Context): เรียกใช้เมื่อนำอินสแตนซ์สุดท้ายที่ใช้งานอยู่ของผู้ให้บริการออกonReceive(Context, Intent): สกัดกั้นการออกอากาศของแพลตฟอร์มทุกรายการก่อนเมธอดเรียกกลับที่เฉพาะเจาะจง คุณต้องตรวจสอบว่าตรรกะตัวรับที่กำหนดเอง ที่คุณเขียนเรียกใช้super.onReceive(context, intent)และ ต้องไม่เรียกใช้goAsyncด้วยตนเอง เนื่องจาก Glance จะกำหนดเส้นทางการทำงาน แบบไม่พร้อมกันโดยอัตโนมัติ
รับ Intent การออกอากาศของวิดเจ็ต
GlanceAppWidgetReceiver จะกรองและจัดการ Intent การออกอากาศของวิดเจ็ตแพลตฟอร์มพื้นฐานต่อไปนี้เบื้องหลัง
ACTION_APPWIDGET_UPDATEACTION_APPWIDGET_DELETEDACTION_APPWIDGET_ENABLEDACTION_APPWIDGET_DISABLEDACTION_APPWIDGET_OPTIONS_CHANGED
สร้าง UI
ข้อมูลโค้ดต่อไปนี้แสดงวิธีสร้าง 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กำหนดโดยใช้แลมบ์ดา ลำดับมีความสำคัญ
คุณสามารถเปลี่ยนค่าการจัดแนวหรือใช้ค่าตัวปรับแต่งต่างๆ (เช่น ระยะห่างภายใน) เพื่อเปลี่ยนตำแหน่งและขนาดของคอมโพเนนต์ได้ ดูรายการคอมโพเนนต์ พารามิเตอร์ และตัวปรับแต่งที่มีทั้งหมดสำหรับแต่ละคลาสได้ในเอกสารอ้างอิง
ใช้มุมแบบมน
Android 12 เปิดตัวพารามิเตอร์ระบบเพื่อปรับแต่งรัศมีมุมของ App Widget แบบไดนามิก
system_app_widget_background_radius: ระบุรัศมีมุมของคอนเทนเนอร์พื้นหลังของวิดเจ็ต (ไม่เกิน 28 dp)- รัศมีภายใน: หากต้องการป้องกันไม่ให้เนื้อหาถูกตัดออก ให้คำนวณรัศมีตามสัดส่วนสำหรับเนื้อหาภายในโดยอิงตามเส้นขอบพื้นหลังของระบบ ดังนี้
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>