สร้างวิดเจ็ตแบบง่าย

วิดเจ็ตแอปเป็นมุมมองแอปขนาดเล็กที่คุณสามารถฝังใน เช่น หน้าจอหลัก และรับการอัปเดตเป็นระยะๆ เหล่านี้ จะเรียกว่า วิดเจ็ต ในอินเทอร์เฟซผู้ใช้ และคุณสามารถเผยแพร่ ผู้ให้บริการวิดเจ็ตแอป (หรือผู้ให้บริการวิดเจ็ต) คอมโพเนนต์ของแอปที่ การจัดวิดเจ็ตอื่นๆ เรียกว่าโฮสต์วิดเจ็ตแอป (หรือโฮสต์วิดเจ็ต) รูปที่ 1 แสดงตัวอย่างวิดเจ็ตเพลง

วันที่ ตัวอย่างวิดเจ็ตเพลง
รูปที่ 1 ตัวอย่างวิดเจ็ตเพลง

เอกสารนี้อธิบายวิธีเผยแพร่วิดเจ็ตโดยใช้ผู้ให้บริการวิดเจ็ต สำหรับ รายละเอียดเกี่ยวกับการสร้าง AppWidgetHost ของคุณเองเพื่อ โฮสต์วิดเจ็ตแอป โปรดดูสร้างโฮสต์วิดเจ็ต

ดูข้อมูลเกี่ยวกับวิธีออกแบบวิดเจ็ตได้ที่ภาพรวมวิดเจ็ตของแอป

คอมโพเนนต์ของวิดเจ็ต

หากต้องการสร้างวิดเจ็ต คุณต้องมีคอมโพเนนต์พื้นฐานต่อไปนี้

ออบเจ็กต์ AppWidgetProviderInfo รายการ
อธิบายข้อมูลเมตาสำหรับวิดเจ็ต เช่น เลย์เอาต์ของวิดเจ็ต การอัปเดต และ AppWidgetProvider คลาส AppWidgetProviderInfo ได้รับการกำหนดใน XML เป็น ตามที่อธิบายไว้ในเอกสารนี้
ชั้นเรียน AppWidgetProvider
กำหนดวิธีการพื้นฐานที่ช่วยให้คุณอินเทอร์เฟซแบบเป็นโปรแกรมได้ด้วย วิดเจ็ต เมื่อใช้วิดเจ็ตนี้ คุณจะได้รับประกาศเมื่อมีการอัปเดตวิดเจ็ต เปิดใช้งาน ปิดใช้งาน หรือลบแล้ว คุณประกาศ AppWidgetProvider ใน ไฟล์ Manifest แล้วนำไปใช้ ตามที่อธิบายไว้ในเอกสารนี้
ดูเลย์เอาต์
กำหนดเลย์เอาต์เริ่มต้นสำหรับวิดเจ็ต การออกแบบกำหนดไว้ใน XML ตามที่อธิบายไว้ในเอกสารนี้

รูปที่ 2 แสดงให้เห็นว่าองค์ประกอบเหล่านี้เหมาะกับการประมวลผลโดยรวมของวิดเจ็ตแอปอย่างไร

วันที่ ขั้นตอนการประมวลผลวิดเจ็ตแอป
รูปที่ 2 ขั้นตอนการประมวลผลวิดเจ็ตแอป

หากวิดเจ็ตต้องกำหนดค่าผู้ใช้ ให้ใช้การกำหนดค่าวิดเจ็ตแอป กิจกรรม กิจกรรมนี้ช่วยให้ผู้ใช้แก้ไขการตั้งค่าวิดเจ็ตได้ เช่น เขตเวลาสำหรับวิดเจ็ตนาฬิกา

นอกจากนี้ เรายังขอแนะนำให้ปรับปรุง การจัดวางวิดเจ็ตที่ยืดหยุ่น การเพิ่มประสิทธิภาพเบ็ดเตล็ด วิดเจ็ตขั้นสูง วิดเจ็ตคอลเล็กชัน และการสร้างวิดเจ็ต

ประกาศ XML AppWidgetProviderInfo

ออบเจ็กต์ AppWidgetProviderInfo กำหนดคุณภาพที่สำคัญของวิดเจ็ต กำหนดออบเจ็กต์ AppWidgetProviderInfo ในไฟล์ทรัพยากร XML โดยใช้ <appwidget-provider> แล้วบันทึกลงในโฟลเดอร์ res/xml/ ของโปรเจ็กต์

ตัวอย่างนี้จะแสดงในตัวอย่างต่อไปนี้

<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/example_loading_appwidget"
    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
  • เริ่มตั้งแต่ Android 12 เป็นต้นไป targetCellWidth และ targetCellHeight ระบุขนาดเริ่มต้นของวิดเจ็ตในรูปตาราง เซลล์ แอตทริบิวต์เหล่านี้จะถูกละเว้นใน Android 11 และต่ำลง และสามารถละเว้นได้หากหน้าจอหลักไม่ รองรับเลย์เอาต์แบบตารางกริด
  • minWidth และ แอตทริบิวต์ minHeight ระบุขนาดเริ่มต้นของวิดเจ็ต หน่วย dp หากค่าสำหรับความกว้างหรือความสูงขั้นต่ำของวิดเจ็ตไม่ตรงกัน ขนาดของเซลล์ ค่าจะถูกปัดเศษขึ้นเป็น ขนาดเซลล์ที่ใกล้ที่สุด
เราขอแนะนำให้ระบุ - 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 ระบุกฎที่วิดเจ็ตสามารถปรับขนาดได้ คุณใช้ ที่ทำให้วิดเจ็ตบนหน้าจอหลักปรับขนาดได้ ในแนวนอน แนวตั้ง หรือทั้งสองแกน ผู้ใช้แตะและ กดวิดเจ็ตค้างไว้เพื่อแสดงแฮนเดิลปรับขนาด จากนั้นลากแฮนเดิลแนวนอนหรือแนวตั้งเพื่อเปลี่ยนขนาด และเลย์เอาต์ทั้งหมด ค่าสำหรับแอตทริบิวต์ 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 กำหนดความถี่ที่เฟรมเวิร์กวิดเจ็ตขอการอัปเดตจาก AppWidgetProvider โดยโทรหา onUpdate() Callback Method เราไม่รับประกันว่าการอัปเดตจริงจะเกิดขึ้นในวันที่ ด้วยค่านี้ และเราขอแนะนำให้อัปเดตไม่บ่อยเท่าที่ควร ไม่เกินชั่วโมงละครั้งเพื่อประหยัดแบตเตอรี่ หากต้องการดูรายการข้อควรพิจารณาทั้งหมดในการเลือกระยะเวลาการอัปเดตที่เหมาะสม ดู การเพิ่มประสิทธิภาพสำหรับการอัปเดตวิดเจ็ต เนื้อหา
initialLayout ชี้ไปที่ทรัพยากรเลย์เอาต์ที่กำหนดเลย์เอาต์ของวิดเจ็ต
configure กำหนดกิจกรรมที่เปิดขึ้นเมื่อผู้ใช้เพิ่มวิดเจ็ต ซึ่งช่วยให้กำหนดค่าพร็อพเพอร์ตี้ของวิดเจ็ตได้ โปรดดู อนุญาตให้ผู้ใช้กำหนดค่าวิดเจ็ต ตั้งแต่ Android 12 เป็นต้นไป แอปสามารถข้ามช่วงเริ่มต้น การกำหนดค่า โปรดดูใช้ การกำหนดค่าเริ่มต้นของวิดเจ็ตเพื่อดูรายละเอียด
description ระบุคำอธิบายสำหรับเครื่องมือเลือกวิดเจ็ตที่จะแสดงสำหรับ วิดเจ็ต เปิดตัวใน Android 12
previewLayout (Android 12) และ previewImage (Android 11 และต่ำกว่า)
  • เริ่มตั้งแต่ Android 12 เป็นต้นไป แอตทริบิวต์ previewLayout ระบุการแสดงตัวอย่างที่รองรับการปรับขนาด ที่คุณระบุเป็นเค้าโครง XML ซึ่งตั้งค่าเป็นขนาดเริ่มต้นของวิดเจ็ต โดยหลักการแล้ว XML การจัดวางที่ระบุเป็นแอตทริบิวต์นี้เป็น XML การออกแบบเดียวกับ วิดเจ็ตจริงที่มีค่าเริ่มต้น ตามจริง
  • ใน Android 11 หรือต่ำกว่า previewImage ระบุหน้าตัวอย่างของวิดเจ็ตที่มีลักษณะอย่างไรหลังจาก ซึ่งผู้ใช้จะเห็นเมื่อเลือกวิดเจ็ตแอป หากไม่ ผู้ใช้จะเห็นไอคอน Launcher ของแอปแทน ช่วงเวลานี้ สอดคล้องกับแอตทริบิวต์ android:previewImage ใน องค์ประกอบ <receiver> ในองค์ประกอบ AndroidManifest.xml ไฟล์
หมายเหตุ: เราขอแนะนำให้ระบุทั้ง previewImage และ previewLayout เพื่อให้แอปของคุณเลิกใช้ เป็นการใช้ previewImage หากอุปกรณ์ของผู้ใช้ไม่รองรับ previewLayout ดูรายละเอียดเพิ่มเติมได้ที่ ความเข้ากันได้แบบย้อนหลังกับการปรับขนาด ตัวอย่างวิดเจ็ต
autoAdvanceViewId ระบุรหัสมุมมองของมุมมองย่อยของวิดเจ็ตที่เพิ่มขั้นสูงอัตโนมัติด้วย โฮสต์ของวิดเจ็ต
widgetCategory ประกาศว่าจะแสดงวิดเจ็ตบนหน้าจอหลักได้หรือไม่ (home_screen) หน้าจอล็อก (keyguard) หรือ ทั้ง 2 อย่าง สำหรับ Android 5.0 ขึ้นไปจะใช้ได้เฉพาะ home_screen
widgetFeatures ประกาศฟีเจอร์ที่วิดเจ็ตรองรับ ตัวอย่างเช่น ถ้าคุณต้องการ วิดเจ็ตของคุณเพื่อใช้การกำหนดค่าเริ่มต้นเมื่อผู้ใช้เพิ่มวิดเจ็ต ให้ระบุ ทั้ง configuration_optional และ reconfigurable การดำเนินการนี้จะข้ามการเปิดกิจกรรมการกำหนดค่าหลังจากผู้ใช้ เพิ่มวิดเจ็ต ผู้ใช้ยังคงสามารถ กำหนดค่าวิดเจ็ตใหม่ หลังจากนั้น

ใช้คลาส AppWidgetProvider เพื่อจัดการการเผยแพร่วิดเจ็ต

ชั้นเรียน AppWidgetProvider จะจัดการการเผยแพร่วิดเจ็ตและอัปเดตวิดเจ็ต เพื่อตอบสนองต่อเหตุการณ์ในวงจรชีวิตของวิดเจ็ต ส่วนต่อไปนี้จะอธิบายวิธี ประกาศ AppWidgetProvider ในไฟล์ Manifest แล้วนำไปใช้

ประกาศวิดเจ็ตในไฟล์ Manifest

ก่อนอื่น ให้ประกาศคลาส AppWidgetProvider ใน AndroidManifest.xml ของแอป ดังที่ปรากฏในตัวอย่างต่อไปนี้

<receiver android:name="ExampleAppWidgetProvider"
                 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/example_appwidget_info" />
</receiver>

องค์ประกอบ <receiver> ต้องการแอตทริบิวต์ android:name ซึ่งระบุ AppWidgetProvider ที่วิดเจ็ตใช้ ต้องไม่ส่งออกคอมโพเนนต์ ยกเว้นกรณีที่กระบวนการแยกต่างหากจำเป็นต้องประกาศไปยัง AppWidgetProvider ซึ่ง มักจะไม่เป็นเช่นนั้น

องค์ประกอบ <intent-filter> ต้องมีองค์ประกอบ <action> ที่มีองค์ประกอบ android:name แอตทริบิวต์นี้ระบุว่า AppWidgetProvider ยอมรับ ACTION_APPWIDGET_UPDATE ออกอากาศ นี่เป็นการแจ้งเตือนเดียวที่คุณต้องประกาศอย่างชัดแจ้ง AppWidgetManager ส่งการกระจายข้อมูลวิดเจ็ตอื่นๆ ทั้งหมดไปยัง AppWidgetProvider โดยอัตโนมัติเป็น ตามความจำเป็น

องค์ประกอบ <meta-data> ระบุทรัพยากร AppWidgetProviderInfo และ ต้องมีแอตทริบิวต์ต่อไปนี้

  • android:name: ระบุชื่อข้อมูลเมตา ใช้ android.appwidget.provider เพื่อระบุข้อมูลเป็น ข้อบ่งชี้ AppWidgetProviderInfo
  • android:resource: ระบุทรัพยากร AppWidgetProviderInfo ตำแหน่งนั้น

ใช้คลาส AppWidgetProvider

ขยายเวลาสำหรับคลาส AppWidgetProvider BroadcastReceiver ในฐานะ สำหรับจัดการการเผยแพร่วิดเจ็ต จะได้รับเฉพาะเหตุการณ์ ข้อความที่เกี่ยวข้องกับวิดเจ็ต เช่น เมื่อวิดเจ็ตมีการอัปเดต ลบ เปิดใช้งาน และปิดใช้งานแล้ว เมื่อเหตุการณ์การออกอากาศเหล่านี้เกิดขึ้น จะมีการดำเนินการต่อไปนี้ มีการเรียกเมธอด AppWidgetProvider ดังนี้

onUpdate()
เรียกว่าเพื่ออัปเดตวิดเจ็ตตามช่วงเวลาที่กำหนดโดย updatePeriodMillis ใน AppWidgetProviderInfo โปรดดูตาราง ซึ่งอธิบายแอตทริบิวต์วิดเจ็ตเพิ่มเติมในหน้านี้สำหรับ ข้อมูลเพิ่มเติม
วิธีนี้เรียกอีกอย่างว่าเมื่อผู้ใช้เพิ่มวิดเจ็ต ซึ่งจะดำเนินการ การตั้งค่าที่จำเป็น เช่น การกำหนดเครื่องจัดการเหตุการณ์สำหรับ ออบเจ็กต์ View หรือการเริ่มต้นงานเพื่อโหลดข้อมูล แสดงในวิดเจ็ต แต่ถ้าคุณประกาศกิจกรรมการกำหนดค่าโดยไม่มี แฟล็ก configuration_optional ระบบจะไม่เรียกใช้เมธอดนี้เมื่อผู้ใช้ เพิ่มวิดเจ็ต แต่จะเรียกใช้การอัปเดตในครั้งต่อๆ ไป ซึ่งเป็น ความรับผิดชอบของกิจกรรมการกำหนดค่าในการดำเนินการอัปเดตครั้งแรก การกำหนดค่าเสร็จสมบูรณ์ โปรดดูข้อมูลเพิ่มเติมที่อนุญาตให้ผู้ใช้กำหนดค่าวิดเจ็ตของแอป
การติดต่อกลับที่สำคัญที่สุดคือ onUpdate() โปรดดูจัดการกิจกรรมด้วย onUpdate()ชั้นเรียนในหน้านี้สำหรับข้อมูลเพิ่มเติม
onAppWidgetOptionsChanged()

โดยจะมีการเรียกเมื่อวางวิดเจ็ตเป็นครั้งแรก และทุกครั้งที่มีวิดเจ็ต ปรับขนาดแล้ว ใช้ Callback นี้เพื่อแสดงหรือซ่อนเนื้อหาตามขนาดของวิดเจ็ต ดูช่วงขนาดและเริ่มตั้งแต่ Android 12 เป็นต้นไป รายการขนาดที่เป็นไปได้ที่อินสแตนซ์วิดเจ็ตจะใช้ได้ โดยการเรียก getAppWidgetOptions() ซึ่งแสดงผล Bundle ที่มี ดังต่อไปนี้:

  • OPTION_APPWIDGET_MIN_WIDTH: มีขอบเขตล่างของความกว้างในหน่วย dp ของอินสแตนซ์วิดเจ็ต
  • OPTION_APPWIDGET_MIN_HEIGHT: มีขอบเขตล่างของความสูงในหน่วย dp ของอินสแตนซ์วิดเจ็ต
  • OPTION_APPWIDGET_MAX_WIDTH: มีขอบเขตบนของความกว้างในหน่วย dp ของอินสแตนซ์วิดเจ็ต
  • OPTION_APPWIDGET_MAX_HEIGHT: มีขอบเขตบนของความสูงในหน่วย dp ของอินสแตนซ์วิดเจ็ต
  • OPTION_APPWIDGET_SIZES: มีรายการขนาดที่เป็นไปได้ (List<SizeF>) ในหน่วย dp ซึ่ง ของวิดเจ็ตได้ เปิดตัวใน Android 12
onDeleted(Context, int[])

ระบบจะเรียกใช้ทุกครั้งที่มีการลบวิดเจ็ตออกจากโฮสต์วิดเจ็ต

onEnabled(Context)

โดยจะเรียกใช้เมื่อมีการสร้างอินสแตนซ์ของวิดเจ็ตเป็นครั้งแรก ตัวอย่างเช่น หากผู้ใช้เพิ่มวิดเจ็ตของคุณ 2 อินสแตนซ์ จะเรียกว่า เป็นครั้งแรก ถ้าต้องการเปิดฐานข้อมูลใหม่หรือทำการตั้งค่าอื่นๆ กำหนดให้ดำเนินการแค่ครั้งเดียวสำหรับอินสแตนซ์วิดเจ็ตทั้งหมด ก็ควรที่จะ สิ่งที่ควรทำ

onDisabled(Context)

ซึ่งจะเรียกว่าเมื่อมีการลบวิดเจ็ตอินสแตนซ์สุดท้ายออกจาก วิดเจ็ต ตรงนี้คือส่วนที่คุณล้างข้อมูลงานที่ทำใน onEnabled(Context) เช่น การลบฐานข้อมูลชั่วคราว

onReceive(Context, Intent)

ระบบจะเรียกใช้ทุกครั้งเมื่อมีการออกอากาศทุกครั้งและก่อนที่จะมีการเรียกกลับก่อนหน้านี้ โดยปกติคุณไม่จำเป็นต้องใช้วิธีนี้เนื่องจากค่าเริ่มต้น การใช้งาน AppWidgetProvider จะกรองการประกาศและการเรียกวิดเจ็ตทั้งหมด วิธีการก่อนหน้าตามความเหมาะสม

คุณต้องประกาศการใช้งานชั้นเรียน AppWidgetProvider เป็นการออกอากาศ โดยใช้องค์ประกอบ <receiver> ใน AndroidManifest โปรดดูการประกาศ ในไฟล์ Manifest ในหน้านี้สำหรับข้อมูลเพิ่มเติม

จัดการเหตุการณ์ด้วยคลาส onUpdate()

AppWidgetProvider Callback ที่สำคัญที่สุดคือ onUpdate() เนื่องจาก เรียกเมื่อเพิ่มวิดเจ็ตแต่ละรายการลงในโฮสต์ เว้นแต่ว่าคุณจะใช้การกำหนดค่า กิจกรรมที่ไม่มีแฟล็ก configuration_optional หากวิดเจ็ตของคุณยอมรับ เหตุการณ์การโต้ตอบของผู้ใช้ จากนั้นลงทะเบียนเครื่องจัดการเหตุการณ์ใน Callback นี้ ถ้า วิดเจ็ตของคุณจะไม่สร้างไฟล์หรือฐานข้อมูลชั่วคราว หรือทำงานอื่น ที่ต้องล้างข้อมูล onUpdate() อาจเป็นวิธีเดียวในการติดต่อกลับที่คุณ ต้องกำหนด

ตัวอย่างเช่น ถ้าคุณต้องการวิดเจ็ตซึ่งมีปุ่มที่จะเปิดกิจกรรมเมื่อ ด้วยการแตะ คุณสามารถใช้การติดตั้งใช้งาน AppWidgetProvider ต่อไปนี้ได้

Kotlin

class ExampleAppWidgetProvider : AppWidgetProvider() {

    override fun onUpdate(
            context: Context,
            appWidgetManager: AppWidgetManager,
            appWidgetIds: IntArray
    ) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        appWidgetIds.forEach { appWidgetId ->
            // Create an Intent to launch ExampleActivity.
            val pendingIntent: PendingIntent = PendingIntent.getActivity(
                    /* context = */ context,
                    /* requestCode = */  0,
                    /* intent = */ Intent(context, ExampleActivity::class.java),
                    /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
            )

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            val views: RemoteViews = RemoteViews(
                    context.packageName,
                    R.layout.appwidget_provider_layout
            ).apply {
                setOnClickPendingIntent(R.id.button, pendingIntent)
            }

            // Tell the AppWidgetManager to perform an update on the current
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views)
        }
    }
}

Java

public class ExampleAppWidgetProvider extends AppWidgetProvider {

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // Perform this loop procedure for each widget that belongs to this
        // provider.
        for (int i=0; i < appWidgetIds.length; i++) {
            int appWidgetId = appWidgetIds[i];
            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(
                /* context = */ context,
                /* requestCode = */ 0,
                /* intent = */ intent,
                /* flags = */ PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE
            );

            // Get the layout for the widget and attach an onClick listener to
            // the button.
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.example_appwidget_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current app
            // widget.
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

AppWidgetProvider นี้กำหนดเฉพาะเมธอด onUpdate() โดยใช้เพื่อ สร้าง PendingIntent ที่เปิดตัว Activity และแนบไว้กับองค์ประกอบ โดยใช้ setOnClickPendingIntent(int, PendingIntent) โดยมีการวนซ้ำที่วนซ้ำแต่ละรายการ ใน appWidgetIds ซึ่งเป็นอาร์เรย์ของรหัสที่ระบุวิดเจ็ตแต่ละรายการที่สร้างโดย ผู้ให้บริการรายนี้ หากผู้ใช้สร้างวิดเจ็ตมากกว่า 1 อินสแตนซ์ เพราะทุกแอปจะอัปเดตพร้อมกัน อย่างไรก็ตาม มีเพียงกำหนดการของ updatePeriodMillis เดียวเท่านั้น วิดเจ็ตมีการจัดการสำหรับทุกอินสแตนซ์ ตัวอย่างเช่น หากกำหนดการอัปเดต คือทุกสองชั่วโมง และมีการเพิ่มวิดเจ็ตอีกครั้ง หนึ่งชั่วโมงหลังจากครั้งแรก ทั้งคู่ก็ได้รับการอัปเดตตามระยะเวลาที่กำหนดโดย ระบบจะไม่สนใจระยะเวลาการอัปเดตแรก และระยะเวลาการอัปเดตที่สอง ทั้ง 2 คนอัปเดตทุก 2 อย่าง ไม่ใช่ทุกชั่วโมง

โปรดดู ExampleAppWidgetProvider.java คลาสตัวอย่างเพื่อดูรายละเอียดเพิ่มเติม

รับ Intent ต่างๆ ในการออกอากาศวิดเจ็ต

AppWidgetProvider เป็นคลาสช่วยอำนวยความสะดวก ถ้าคุณต้องการรับวิดเจ็ต ออกอากาศโดยตรง คุณสามารถใช้ BroadcastReceiver ของคุณเองหรือลบล้าง เวลา การติดต่อกลับของ onReceive(Context,Intent) ที่ควรคำนึงถึงคือ ดังต่อไปนี้:

สร้างเลย์เอาต์วิดเจ็ต

คุณต้องกำหนดการออกแบบเริ่มต้นสำหรับวิดเจ็ตใน XML และบันทึกไว้ใน ไดเรกทอรี res/layout/ ของโปรเจ็กต์ โปรดดูที่การออกแบบ หลักเกณฑ์เพื่อดูรายละเอียด

การจัดวางวิดเจ็ตนั้นไม่ซับซ้อนหากคุณคุ้นเคยกับ การออกแบบ อย่างไรก็ตาม โปรดระวังว่าวิดเจ็ต อิงจาก RemoteViews ซึ่งไม่รองรับเลย์เอาต์หรือวิดเจ็ตมุมมองทุกประเภท คุณใช้การตั้งค่าที่กำหนดเองไม่ได้ ข้อมูลพร็อพเพอร์ตี้หรือคลาสย่อยของข้อมูลพร็อพเพอร์ตี้ที่ RemoteViews รองรับ

RemoteViews ยังรองรับ ViewStub ซึ่งเป็นViewขนาดศูนย์ที่มองไม่เห็น ซึ่งคุณนำมาใช้เพื่อเพิ่มเลย์เอาต์แบบ Lazy Loading ได้ ทรัพยากรขณะรันไทม์

รองรับลักษณะการทำงานแบบเก็บสถานะ

Android 12 เพิ่มการรองรับลักษณะการทำงานแบบเก็บสถานะโดยใช้สิ่งต่อไปนี้ คอมโพเนนต์ที่มีอยู่

วิดเจ็ตยังไม่เก็บสถานะ แอปของคุณต้องจัดเก็บรัฐและลงทะเบียน เหตุการณ์การเปลี่ยนแปลงสถานะ

วันที่ ตัวอย่างวิดเจ็ตรายการช็อปปิ้งที่แสดงลักษณะการทำงานแบบเก็บสถานะ
รูปที่ 3 ตัวอย่างลักษณะการทำงานของการเก็บสถานะ

ตัวอย่างโค้ดต่อไปนี้แสดงวิธีติดตั้งคอมโพเนนต์เหล่านี้

Kotlin

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true)

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2)

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
        R.id.my_checkbox,
        RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent)
)

Java

// Check the view.
remoteView.setCompoundButtonChecked(R.id.my_checkbox, true);

// Check a radio group.
remoteView.setRadioGroupChecked(R.id.my_radio_group, R.id.radio_button_2);

// Listen for check changes. The intent has an extra with the key
// EXTRA_CHECKED that specifies the current checked state of the view.
remoteView.setOnCheckedChangeResponse(
    R.id.my_checkbox,
    RemoteViews.RemoteResponse.fromPendingIntent(onCheckedChangePendingIntent));

มีรูปแบบ 2 แบบ โดย 1 แบบกำหนดเป้าหมายเป็นอุปกรณ์ที่ใช้ Android 12 หรือ สูงขึ้นใน res/layout-v31 และการกำหนดเป้าหมายอื่นๆ ก่อนหน้านี้ Android 11 หรือต่ำกว่าในโฟลเดอร์ res/layout เริ่มต้น

ใช้มุมโค้งมน

Android 12 ขอแนะนําพารามิเตอร์ระบบต่อไปนี้เพื่อตั้งค่า รัศมีมุมโค้งมนของวิดเจ็ต

  • system_app_widget_background_radius: รัศมีมุมของพื้นหลังวิดเจ็ต ซึ่งมีค่าไม่เกิน 28 dp

  • system_app_widget_inner_radius: รัศมีมุมของทุกมุมมองภายในวิดเจ็ต เท่ากับ 8 dp รัศมีของพื้นหลังน้อยกว่า เพื่อปรับแนวให้พอดีเมื่อใช้ 8 dp ระยะห่างจากขอบ

ตัวอย่างต่อไปนี้แสดงวิดเจ็ตที่ใช้ system_app_widget_background_radiusสำหรับมุมของวิดเจ็ตและ system_app_widget_inner_radius สำหรับการดูข้อมูลภายในวิดเจ็ต

วันที่ วิดเจ็ตแสดงรัศมีของพื้นหลังวิดเจ็ตและมุมมองภายในวิดเจ็ต
รูปที่ 4 มุมโค้งมน

1 มุมของวิดเจ็ต

2 มุมของมุมมองภายในวิดเจ็ต

ข้อควรพิจารณาที่สำคัญสำหรับมุมโค้ง

  • Launcher และผู้ผลิตอุปกรณ์ของบุคคลที่สามสามารถลบล้าง พารามิเตอร์ system_app_widget_background_radius ให้มีขนาดเล็กกว่า 28 dp พารามิเตอร์ system_app_widget_inner_radius จะน้อยกว่า 8 dp เสมอ ค่าของ system_app_widget_background_radius
  • หากวิดเจ็ตไม่ได้ใช้ @android:id/background หรือระบุพื้นหลัง ที่ตัดคลิปเนื้อหาตามโครงร่าง โดยใช้ android:clipToOutline ตั้งค่าเป็น true— Launcher จะระบุพื้นหลังโดยอัตโนมัติและ ตัดคลิปวิดเจ็ตโดยใช้รูปสี่เหลี่ยมผืนผ้ามุมมนสูงสุด 16 dp โปรดดูหัวข้อตรวจสอบว่าวิดเจ็ตใช้งานได้กับ Android 12

สำหรับความเข้ากันได้ของวิดเจ็ตกับ Android เวอร์ชันก่อนหน้า เราขอแนะนำให้ การกำหนดแอตทริบิวต์ที่กำหนดเอง และใช้ธีมที่กำหนดเองเพื่อแทนที่แอตทริบิวต์เหล่านั้น Android 12 ดังที่แสดงในไฟล์ XML ตัวอย่างต่อไปนี้

/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>

/layout/my_widget_layout.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  ...
  android:background="@drawable/my_widget_background" />