web analytics

Android Code : สร้าง App Widget เบื้องต้น ตอนที่ 2

cover-2

จากบทความที่แล้ว ได้พูดถึงการสร้าง App Widget แบบง่าย การทำให้รองรับการปรับขนาดได้ บทความนี้จะพามาลองทำเพิ่มเติมเกี่ยวกับ Multi widget แล้วก็การใช้งาน ListView ใน Widget

 

ตอนที่ 1

http://benzneststudios.com/blog/android/how-to-create-app-widget-1/

 

การทำ Multi Widget

ใน 1 แอปสามารถมีได้หลาย Widget เราจะมาลองสร้าง Widget เพิ่มอีก 1 ตัวกัน
วิธีการก็ใช้หลักการเดียวกับในบทความตอนที่ 1 คือ

สร้าง WidgetProvider
สร้าง Layout
สร้าง Metadata และกำหนด layout ใน metadata
กำหนด WidgetProvider  เป็น Receiver ใน AndroidManifest.xml
Implement ตัว WidgetProvider

เราจะมาลองเพิ่ม Widget ListView ตัวใหม่กันอีก 1 ตัว
ถ้าอ่านบทความตอนที่ 1 มาแล้วก็ลุยเลย

MyWidgetListViewProvider.java

 

layout/app_widget_listview.xml
เพื่อเตรียมทำ listView ขอใส่ listView ไว้เลย ใส่ id ให้มันด้วย

11

 

xml/app_widget_listview.xml

 

AndroidManifest.xml

 

ทำการ implement ส่วนของ onUpdate() ใน MyWidgetListViewProvider
ให้สร้าง remoteView จาก layout ที่เตรียมไว้ แล้วสั่ง updateWidget เพื่อดูว่า widget ที่สองทำงานมัย

 

รันดูผลลัพธ์

จะเห็นว่าในหน้าเลือก Widget ที่แอปของเราจะมี widget ให้เลือก 2 อัน คืออันเก่าและอันใหม่นั่นเอง

a4

 

สร้าง Layout ของแถวใน ListView

ต่อมาเราจะเตรียมส่วนของแถวใน ListView กัน

สร้าง layout ของแถว แล้วใส่ id ให้เรียบร้อย

layout/row_food.xml

12

 

สร้างคลาส MyRemoteViewFactory

คลาสนี้จะทำงานคล้ายกับ Adapter มันมีหน้าที่สร้าง RemoteView ไปแสดงใน ListView
การ implement ขอเว้นไว้ก่อน เดี๋ยวกลับมาเขียน

 

สร้างคลาส MyWidgetListViewService

คลาสนี้เป็นคลาส service ที่คอย blinding ตัว Factory กับตัว MyWidgetProvider
เวลาเรา scroll ใน listView มันก็จะทำงานเหมือนเชื่อมตัว ListView ใน MyWidgetProvider กับข้อมูลที่จะสร้างใน factory

 

กำหนด MyWidgetListViewService เป็น service

ไปที่ AndroidManifest.xml ให้ไปกำหนดคลาส MyWidgetListViewService เป็น service
และ permission BIND_REMOTEVIEWS

 

เขียนส่วน onUpdate() ใน MyWidgetListViewProvider

ให้ลบ onUpdate() อันเดิมออก เราจะมาเขียนใหม่ ให้เป็นแบบ listView
หลักการจะคล้ายของเดิม คือ ต้องสร้าง Intent ก่อนซึ่งในที่นี้คือ MyWidgetListViewService ซึ่งทำหน้าที่เชื่อม Factory (Adapter) จากนั้นก็ setRemoteAdapter โดยใส่เจ้า listView กับ intent นี้ลงไป

 

MyRemoteViewFactory

ตัว remoteViewFactory ที่เราเว้นไว้ ให้ override พวก method ที่ต้อง implement ออกมาให้หมด
จริงๆมัน เหมือน BaseAdapter เลย มี getCount() , getViewAt()

อันนี้ผมสมุติว่าที่ onCreate ก็สร้างลิสอาหารขึ้นมา แล้วที่ getViewAt() ก็ทำการสร้าง RemoteView จาก layout แถวที่เตรียมไว้
ใส่ข้อมูลให้เรียบร้อย จบพิธี

คำเตือน ที่ getViewTypeCount() ไม่ควรเป็น 0 เพราะเดี๋ยวมันจะไม่ขึ้น ระวังด้วย

สรุปที่ส่วนที่จำเป็น คือ getViewAt() , getCount() , getViewTypeCount()

 

รันดูผลลัพธ์

a5

 

ใส่ event Click ให้กับ รายการใน ListView

เริ่มต้นจากการกำหนด PendingIntentTemplate คือ การกำหนดว่าทุก รายการจะมี pendingIntent แบบนี้นะ
กดแล้วจะไป Activity ไหน โดยใส่ไว้ใน onUpdate()

 

ต่อมา ก็มาเรียกการใช้งาน pendingIntent ที่ MyRemoteViewFactory
ใน getViewAt(position)

ตรงนี้เราจะทำการ สร้าง Intent และใส่ bundle ให้เรียบร้อย เตรียมส่งไปยัง activity ที่กำหนด
จากนั้นเรียก setOnClickFillIntent แล้ว pendingIntent ก็จะทำงาน

แล้วที่ Activity ก็ไปรอรับ intent และ bundle ได้เลย

 

รันดูผลลัพธ์

คลิกที่รายการใน widget

a6

 

สร้าง App Widget ด้วย Android Studio

เมื่อเข้าใจถึงโครงสร้างของ app widget แล้ว ตัว Android studio มีเครื่องมือช่วยในการสร้างอย่างง่ายดาย
คลิกขวาที่ app > New > Widget > App Widget

13

 

จากนั้นก็สามารถสร้าง Widget ได้ง่ายๆเลย ถ้าติ๊ก configuration screen มันจะ generate configuration activity ให้
ซึ่งในบทความนี้ไม่ได้กล่าวถึง มันก็คือการตั้งค่า widget โดยผู้ใช้ในแอป ไม่ต้องติ๊กก็ได้

14

 

สิ่งที่มัน generate ให้มีทั้ง Widget Class , Layout ของ widget , Metadata xml , ใส่ receiver ให้ใน AndroidManifest ด้วย
และสามารถใช้งาน Widget ได้ทันที เริ่ดจีจี

15

 

แต่ทั้งนี้ทั้งนั้น เราก็ต้องเข้าใจที่มาที่ไป หลักการทำงานก่อนจะดีกว่านะ

 

 

Source code

https://gist.github.com/anonymous/3fa540cc1b7450b7e5b63c5f39563276

 

จบแล้ว

การทำ Widget แบบแสดงข้อมูลทั่วไป ไม่มีอะไรซับซ้อนมากนัก แต่การทำ Widget แบบ Collection มีความซับซ้อนขึ้นมาหน่อยตรงที่มันใช้งานต่างจากพวก Adapter เพราะมันต้องใช้ RemoteViews นั่นเอง หากใช้งาน ListView ได้ พวก GridView ,StackView ก็ไม่ต่างกัน และหัวใจสำคัญคือ onUpdate() ที่ต้องเช็คพวกขนาดของ widget สร้าง RemoteView แล้วอัพเดทข้อมูลให้ถูกต้อง

หากมีคำถามหรือ คำแนะนำสามารถคอมเม้นไว้ได้เลยครับ

ขอบคุณครับ

 

Reference

https://developer.android.com/guide/topics/appwidgets/index.html
http://stackoverflow.com/questions/14299187/android-start-activity-when-pressing-widget-listview-item