บทความ Android วันนี้ ขอนำเสนอเรื่อง การทำ Load More ให้กับ ListView ไม่ใช่การทำ Load More ที่มี Button นะ แต่เป็นการใช้การ Scroll เพื่อทำการโหลดข้อมูลใหม่มาแสดงใน ListView
ก่อนที่จะไปเริ่มทำ Load More ListView ด้วยการ Scrolling หากใครยังไม่รู้จัก ListView ก็อ่านหัวข้อด้านล่างเพิ่มเติมครับ
Create Project
เริ่มแรก ก็ทำการสร้างโปรเจ็คขึ้นมาเลย
โปรเจ็คนี้ ไมไ่ด้ใช้ 3rd party หรือ Library อะไรเพิ่มเติมเลย ฉะนั้นก็ไม่ต้องทำอะไรเพิ่ม เปิดไฟล์ MyActivity.java
ขึ้นมา ทำการแก้ไข โดยเปลี่ยนจากการ extends คลาส Activity
เป็น ListActivity
แทน เพื่อความสะดวก และรวดเร็วครับ
ListActivity คือ Activity ที่่มี ListView อยู่ภายในอยู่แล้ว เราไม่ต้องสร้าง Layout หรือทำการเชื่อม ListView กลับโปรแกรมอีก เพียงแค่เรียก getListView()
ก็พอ
MyActivity.java
สร้าง ListView
ต่อมาทำการสร้าง ListView แบบง่ายๆขึ้นมา โดยผมทำการวนลูป เพื่อสร้างข้อมูล จำนวน 300 ค่า ใส่ตัวแปร mTotalData
และ ListView แสดงข้อมูลที่ละ 20 แถว เก็บค่าใส่ตัวแปร mCurrentData
ดังนี้
จากโค๊ดด้านบน ตรงส่วน getData()
ก็คือทำการดึงข้อมูลมา 20 ค่า จากทั้งหมด 300 ค่า แล้วมาแสดงใน ListView
ฟังค์ชันนี้จะใช้ mCurrentPage
และ mItemPerRow
เพื่อเอาไว้ดึงข้อมูลจาก mTotalData
นะครับ ในส่วน mCurrentPage
จะเอาไว้ระบุว่า เมื่อมีการ Load More ค่านี้ก็จะเพิ่มขึ้น 1 ก็จะทำการดึงข้อมูลในอีก 20 ชุดถัดไป (ตอนนี้ยังไม่มี Load More)
ได้ผลดังนี้
ต่อมา เราจะทำการเพิ่มข้อมูล เมื่อเราทำการ Scroll จนถึง item สุดท้ายแล้ว เมธอดที่ใช้คือ ListView.setOnScrollListener()
คลาสนี้ทำการ extends ListActivity
ฉะนั้น เราสามารถเรียก getListView()
ได้เลย แบบนี้
จากโค๊ดด้านบน มีตัวแปรเพิ่มเข้ามาคือ isLoadMore
เอาไว้เช็คสถานะเพื่อไม่ให้ Load More ซ้ำกันเวลาเราทำการ scroll ตัวต่อไปคือ mHandler
เป็น runnable object เอาไว้จำลอง ให้การดึงข้อมูล มีการดีเลย์ซักเล็กน้อย เสมือน ดึงข้อมูลมาจาก Web Service :D
ต่อมา onScrollListener()
เมื่อเราทำการ scroll มันจะไปเรียกเมธอด onScroll()
โดย parameter ของ onScroll()
ที่เราต้องสนใจ จะมีดังนี้
firstVisibleItem
: คือ ตำแหน่ง ของไอเท็มที่เราเห็นบน ListView ตำแหน่งแรกสุดบนหน้าจอ
visibleItemCount
: คือ จำนวน ไอเท็ม/แถว ที่เราสามารถมองเห็นได้ในขณะนั้นๆ (ยิ่งจอใหญ่ยิ่งเห็นเยอะ)
totalItemCount
: คือ จำนวน ไอเท็ม/แถว ทั้งหมดของ ListView
ภายในเมธอด ที่เอาไว้เช็คว่า เมื่อไหร่ ควรจะ Load More ก็คือ
การนำตำแหน่งของไอเท็มบนสุดของหน้าจอ มาบวกกับ จำนวนไอเท็มทั้งหมดที่หน้าจอจะเห็นได้ ก็จะสามารถรู้ตำแหน่ง ไอเท้มสุดท้ายได้ เมื่อ Scroll จนถึงไอเท้มสุดท้าย ก็ไปทำการ getData()
ชุดใหม่ มาใส่ ListView อีกครั้ง
ใช้ adapter.notifyDataSetChanged();
เพื่อสั่งให้ ListView ทำการ render ข้อมูลใหม่ ทดสอบ โปรแกรมดูอีกครั้ง คราวนี้ เมื่อเลื่อนไปสุด ก็จะโหลดข้อมูลมาใหม่ ต่อท้าย mCurrentData
เดิมไปเรื่อยๆ
เพิ่ม ProgressDialog
เมื่อเราทำการ Load More ดึงข้อมูลชุดใหม่มา ขณะที่กำลังทำการดึงข้อมูล เราควรจะมีการตอบสนองต่อผู้ใช้ หรือว่าอะไรก็แล้วแต่ให้รู้ว่าโปรแกรมยังทำงานอยู่ ในตัวอย่างนี้ ก็จะใช้ ProgressDialog
เข้ามาช่วย เมื่อทำการ getData()
ระหว่างนั้นก็จะโชว์ Loading เพื่อรอให้โหลดข้อมูลจนเสร็จ ถึงสั่ง dismiss()
ดังนี้
ด้านบน ใช้ ProgressDialog
แบบ SPINNER และใส่ข้อความว่า Loading...
สั่ง mLoading.show();
เมื่อเริ่มดึงข้อมูล และสั่ง mLoading.dismiss();
เมื่อทำการดึงข้อมูลเสร็จแล้ว
ทดลองรันโปรแกรมอีกรอบ
สรุป
ตัวอย่างนี้ก็เป็นการทำ ListView และการดึงข้อมูลใหม่มาแสดง โดยการใช้การ Scroll ข้อมูลที่ได้ก็จะต่อจากข้อมูลเดิม แต่หากว่า เราไม่อยากให้ข้อมูลมันต่อกันละ แต่อยากให้มันแสดงใหม่เลย เหมือนกับการ refresh ก็ทำได้ โดยการสั่ง clear ข้อมูลใน ListView ซะก่อน และเลื่อนให้ ListView ไปอยู่แถวบนสุด เช่น
ก็ลองๆนำไปประยุกต์ใช้กันดูนะครับ หวังว่าจะเป็นประโยชน์สำหรับผู้ที่กำลังมองหาวิธีทำอยู่นะ
โค๊ดทั้งหมด (มีไฟล์เดียว)