Image Slideshow with Kotlin ViewPager

Datafarm
6 min readAug 18, 2021

สวัสดีครับ วันนี้เราจะมาสร้าง Image Slideshow ใน Android โดยเริ่มต้นจาก App พื้นฐานที่มีมาให้ หลังจากนั้นเราสามารถนำไป reuse กับอีกหลายๆ App ได้ โดยฟังก์ชั่นหลักที่เราต้องการคือ

  • Slideshow สามารถใส่รูป preview ได้มากกว่า 1 รูป
  • เมื่อ Slideshow มีภาพ preview มากกว่า 1 รูป ภาพจะสไลด์เองอัตโนมัติ
  • เมื่อ Slideshow มีภาพ preview มากกว่า 1 รูป สามารถแตะลากเพื่อเลื่อนดู preview อื่นๆ ได้
  • รูป preview แต่ละรูปสามารถแตะเพื่อดูภาพแบบ full image ได้
  • เมื่ออยู่ในหน้าจอแบบ full image สามารถแตะปุ่มกากบาทเพื่อปิด

ในเบื้องต้นจะนำเสนอในรูปแบบ implement ใช้กับตัว Activity เป็นหลัก หากใครยังไม่ได้ติดตั้ง Android Studio บนคอมพิวเตอร์ สามารถเข้าไปดาวน์โหลดได้โดยตรง ที่นี่ เลือกระบบปฏิบัติการที่ตรงกับคอมพิวเตอร์ที่เพื่อนๆ ใช้งานอยู่ หลังจากนั้นให้ทำการติดตั้ง Android Studio ตามคู่มือหลังการติดตั้ง ในส่วนของการรันแอพ เพื่อนๆ สามารถลง Android Emulator ที่มีมาให้เพิ่มเติมผ่าน Android Studio ได้เลย

ส่วนผมนั้นเลือกใช้สมาร์ทโฟน Samsung Galaxy S10+ แทน Emulator เพราะทำงานได้เร็วกว่า หากเพื่อนๆ มีสมาร์ทโฟน Android แบรนด์อื่นๆ อยู่แล้วก็สามารถนำมาใช้งานได้เลย โดยระบบปฏิบัติการขั้นต่ำคือ Android 4.4 Kitkat และต้องทำการเปิด developer mode ที่นี่ โดยสมาร์ทโฟนแต่ละแบรนด์อาจจะมีจุดแตกต่างอยู่บ้างในการเข้าถึงเมนูนี้ พร้อมเตรียมสาย usb สำหรับนำมาต่อกับคอมพิวเตอร์ เพื่อติดตั้งแอพจาก Android Studio ผ่านสาย usb ไปลงที่ตัวเครื่องสมาร์ทโฟน

สร้าง Application ใหม่

  1. เมื่อเตรียมอุปกรณ์และโปรแกรมต่างๆ เรียบร้อยแล้ว เรามาเริ่มสร้างแอ็พตัวแรกขึ้นมากันก่อนเลยโดย เปิดโปรแกรม Android Studio ขึ้นมา แล้วเลือก + Create New Project (หากเพื่อนๆ มีโปรเจคแอ็พที่กำลังทำอยู่แล้วสามารถข้ามขั้นตอน สร้าง Application ใหม่ ไปได้เลย)

2. ในขั้นตอนนี้ส่วนเมนู Templates ทางด้านซ้ายมือให้เลือกเป็น Phone and Tablet แล้วทางด้านขวามือให้เลือกเป็น Basic Activity แล้วคลิก Next ได้เลย

3. ในขั้นตอนนี้ให้เพื่อนๆตั้งชื่อ Name ชื่อของแอ็พ ให้สังเกตว่าชื่อของแอ็พจะกลายเป็นชื่อต่อท้ายส่วนของ Package name ในช่องกรอกข้อมูลลำดับถัดมา ในส่วนของ Package name นั้นมักจะตั้งชื่อเป็นลักษณะ reverse domain เช่นจาก datafarm.com ก็จะกลายเป็น com.datafarm ดังนั้นของผมจึงกลายเป็น com.datafarm.myslideshow ซึ่งควรตั้ง เป็นตัวพิมพ์เล็กทั้งหมด และในช่องที่สามคือตัวโปรเจคของแอ็พว่าเราต้องการให้เก็บไว้ที่ไหน จากนั้นให้กด Finish ได้ทันที

4. หลังจากกด Finish ไปแล้วหน้าต่างใหม่จะปรากฏขึ้นมา และต้องรอสักพักให้ Android Studio ทำการ sync setting ต่างๆ ของตัวโปรเจคขึ้นมาให้เรียบร้อยก่อน สังเกตได้จากแถบการทำงานด้านขวาล่าง หากไม่มีแถบ progress ใดๆ เลยแสดงว่าเราสามารถเริ่มทำงานต่อได้แล้ว

เตรียม assets ที่จำเป็นกับการทำ Slideshow

  1. ภาพ preview image ทั้งหมด 5 รูป และภาพขนาดเต็ม full image หรือจะใช้วิธีการ crop รูปภาพเต็มทำเป็น preview image ก็ได้ ซึ่งผมจะเลือกวิธีการ crop รูปภาพโดยดาวน์โหลดต้นฉบับจาก ที่นี่
  2. สุดท้ายคือภาพกากบาท ไว้สำหรับปิด เมื่ออยู่ในหน้าจอ full image โดยสามารถดาวน์โหลดใช้งานได้ฟรี ที่นี่
  3. ผมจะทำการตั้งชื่อภาพโดย crop รูปไว้ที่ขนาด 512x512 pixels และตั้งชื่อเป็น prev_01.jpg ไปจนถึง prev_05.jpg และภาพขนาดเต็มด้วยชื่อ full_01.jpg ไปจนถึง full_05.jpg ข้อควรระวังคือ วิธีการตั้งชื่อภาพควรใช้เป็นตัวอักษรพิมพ์เล็ก ตัวเลข และเครื่องหมาย _ เท่านั้น
  4. เมื่อได้รูปภาพตามจำนวนที่ต้องการแล้วให้นำมาใส่ไว้ในโฟลเดอร์ MySlideshow/app/src/main/res/drawable

5. หากทำการลากรูปภาพทั้งหมดมาวาง จะขึ้น dialog ดังรูปด้านบน ให้เลือกกด Refactor ได้เลย หลังจากนั้นจะได้ผลลัพธ์ดังรูปด้านล่าง

6. อย่าลืมนำภาพ กากบาท ที่ใช้สำหรับปิดหน้าจอที่แสดงผลแบบ full image มาใส่ด้วย ก็เป็นอันเสร็จขั้นตอนการเตรียม assets

เริ่ม Implement รูปภาพที่นำมาใช้งาน

  1. กลับมาที่หน้าจอหลักใน Android Studio ส่วนตัวผมมักจะเลือกปรับ sidebar ด้านข้างให้เป็นรูปแบบ Project แทน Android เพราะสะดวกกับการทำงานแบบต้อง config ค่าต่างๆ บ่อยๆ มากกว่าซึ่งตรงนี้เพื่อนๆ จะทำตามหรือใช้ในแบบของตัวเองก็ได้ หลังจากนั้นให้เปิดไฟล์ MainActivity.kt ขึ้นมาโดยเข้าไปที่ MySlideshow/app/src/main/java/com/datafarm/myslideshow

2. ประกาศตัวแปร array 2 ชุดสำหรับรูป preview และแบบ full โดยแต่ละ element จะอิงไปที่รูปภาพนั้นๆ ตามชื่อที่เราตั้งไว้ อยู่ในโฟลเดอร์ drawable

สร้าง layout สำหรับ slideshow

  1. ไปที่ MySlideshow/app/src/main/res/layout แล้วคลิกขวา เลือก New > Layout Resource File

2. ในช่อง File name: ตั้งชื่อว่า fragment_slide_view และในช่อง Root element: ให้ใส่ว่า LinearLayout แล้วกด OK ได้เลย

3. จะปรากฏหน้าต่างรูปแบบ xml ให้ลองคลิกที่ปุ่ม Split ทางด้านขวาบนจะช่วยให้มองเห็นทั้ง xml และ design view ไปพร้อมๆ กัน

4. ให้เพิ่ม xml ส่วนของ ImageView เข้ามา พร้อมกำหนด id ให้เป็น imgSlideView จากนั้นให้เซฟไฟล์ เป็นอันเสร็จ

สร้าง layout สำหรับ full image

  1. ไปที่ MySlideshow/app/src/main/res/layout แล้วคลิกขวา เลือก New > Layout Resource File

2. ในช่อง File name: ตั้งชื่อว่า fragment_full_image และในช่อง Root element: ให้ใส่ว่า LinearLayout แล้วกด OK ได้เลย

3. หลังจาก fragment_full_image เปิดขึ้นมาแล้วให้ทำการแก้ไข android:orientation=”vertical” เป็น android:orientation=”horizontal” และ เพิ่มบรรทัด xmlns:app=”http://schemas.android.com/apk/res-auto" เข้ามาก่อนปิด tag ดังรูป

4. สร้าง layout ส่วนที่ใช้แสดงรูปภาพขนาดเต็ม พร้อม ImageView ที่ใช้ในการแสดงผลของรูป กำหนด id ของ ImageView เป็น imgFullView ตามรูป

5. สร้างส่วนของการแสดงผล ปุ่มกากบาท ไว้สำหรับปิดหน้าแสดงรูปภาพแบบเต็มรูป โดยกำหนดให้มี layout สำหรับปุ่มกากบาทต่างหาก และ ImageButton กำหนด id ให้เป็น btnClose ดังรูป เป็นอันเสร็จ layout สำหรับ full image

แก้ไข layout ของ activity_main.xml

  1. ไปที่ MySlideshow/app/src/main/res/layout แล้วเปิดไฟล์ activity_main.xml ขึ้นมา จากนั้นกำหนด layout สำหรับ แสดงผล ViewPager widget component โดยกำหนด id ให้เป็น holdSlideView คือส่วนที่เอาไว้แสดงผล slideshow หลัก หลังจากนี้ก็สามารถนำไปแปะที่ layout ไหนก็ได้

2. โค้ดอื่นๆ ส่วนที่มีอยู่เดิมนอกเหนือจาก root xml แล้วนั้นให้ comment ออกให้หมดโดยใส่ <! — ส่วนที่ไม่ต้องการใช้งาน → ดังรูป เป็นอันเสร็จการแก้ไข

สร้าง adapter class ใหม่สำหรับ slideshow

  1. ต่อไปเราจะทำการสร้าง SlideViewAdapter ขึ้นมา โดยไปที่ sidebar คลิกขวาบน com.datafarm.slideshow แล้วเลือกเมนู New > Kotlin Class/File

2. จะปรากฎหน้าต่างขึ้นมาให้กรอกชื่อ SlideViewAdapter หรือชื่ออื่นๆ ตามที่เพื่อนๆ ต้องการได้เลย หลังจากนั้นดับเบิ้ลคลิกที่คำว่า Class

3. จะปรากฏ class ใหม่ขึ้นมาทางหน้าต่างหลักด้านขวาตามรูป

4. เริ่มต้นด้วยการ import library ที่จำเป็นเข้ามาก่อน

5. จากนั้นทำการ extend class ที่เราสร้างขึ้นมาด้วย PagerAdapter จะเห็นได้ว่ามีการ import library ให้เองอัตโนมัติทางด้านนอก class (หากการ import แบบอัตโนมัติไม่ทำงาน สามารถพิมพ์เพิ่มใส่เข้ามาเองได้ หรือใช้ tooltips ช่วยเหลือ)

เสร็จแล้วให้รับ parameter Context และ IntArray ผ่าน class หลังจากนั้น ให้ทำการประกาศตัวแปรแบบ private ให้กับ Context และ IntArray ที่รับมา โดยที่เราต้องเพิ่มตัวแปรสำหรับ LayoutInflater ขึ้นมาอีกตัว แต่ไม่ต้องรับเป็น parameter ผ่าน class

6. จากจุดนี้เราจะเริ่มทำการ override function เดิมของ PagerAdapter ที่เรา extend มา เริ่มที่ getCount และ isViewFromObject สังเกตว่าเราจะใช้ตัวแปร private แทนค่าภายในฟังก์ชั่นหลัง initialize ทั้งหมด

7. ให้ทำการ override อีกสองฟังก์ชั่นสุดท้ายคือ instantiateItem และ destroyItem ส่วนที่ต้องระวังคือ instantiateItem เราต้องกำหนด layoutInflater ให้ชี้ไปที่ fragment_slide_view และส่วนที่เป็น ImageView ให้ดึงเอา id ที่กำหนดเป็น imgSlideView มาใส่ เป็นอันเสร็จการสร้าง SlideViewAdapter ที่ extend มาจาก PagerAdapter

Implement และแก้ไข MainActivity.kt

1. กลับมาที่ไฟล์ MainActivity.kt ซึ่งก่อนหน้านี้เราได้ทำการ ประกาศตัวแปร รูปทั้งหมดที่เราจะนำมาใช้งาน ให้ทำการประกาศตัวแปรสำหรับ ViewPager และ SlideViewAdapter ที่เราเพิ่งสร้างเสร็จในขั้นตอนก่อนหน้า

จากนั้น ให้ทำการ comment code ตั้งแต่ binding ไปจนถึงบรรทัดสุดท้ายในฟังก์ชั่น onCreate แล้วเพิ่ม setContentView ไปที่ R.layout.activity_main แทน เพื่อให้เรียกหน้า activity_main ที่มี layout แสดงเฉพาะ widget ViewPager ขึ้นมา

2. ยังคงอยู่ภายในฟังก์ชั่น onCreate ด้านล่างสุดของส่วนที่ถูก comment ออกไปแล้ว (เพื่อนๆจะลบโค้ดที่ให้ comment ออกไปเลยก็ได้ หรือจะเก็บไว้อ้างอิงก่อนก็ไม่เสียหาย) ให้ประกาศ viewPager เป็น holdSlideView ซึ่งอ้างถึง widget ViewPager ใน activity_main.xml นั่นเอง

บรรทัดถัดมาให้กำหนดตัวแปร slideViewAdapter มีค่าเป็น SlideViewAdater class แล้วส่ง parameter application context กับรูป preview ที่ประกาศไว้

จากนั้นบรรทัดที่สาม ทำการกำหนด adapter ของ viewPager ของเราให้มีค่าเป็น slideViewAdapter มาถึงตรงนี้ในส่วนของ content มีการเชื่อมโยงกันครบแล้ว แต่เรายังต้องกำหนดให้ viewPager รับ event การแตะบนหน้าจอหรือ setOnTouchListener นั่นเอง แต่การรับ setOnTouchListener event นั้นยังไม่พอสำหรับการใช้งานเพราะผลที่ได้จะทำให้ รูปภาพทั้งหมดถูกโยนค่าออกมา ดังนั้นจึงประกาศ TapGestureListener เพิ่มขึ้นมา

3. จากขั้นตอนก่อนหน้าจะเกิด error เนื่องจากเราไม่ได้ประกาศ TapGestureListener ไว้ก่อนเรียกใช้งาน ดังนั้น ออกมาจาก ฟังก์ชั่น onCreate แล้วสร้าง inner class ขึ้นมาดังรูป โดยภายในฟังก์ชั่นให้ทำการ override onSingleTapConfirmed จากนั้นให้เรียกใช้งานฟังก์ขั่น showFullImage และส่ง parameter viewPager.currentItem ลงไป ซึ่งมีค่าเท่ากับ index ของ array ของรูป preview นั่นเอง

4. ยังคงมี error ตามมาจากการที่ยังไม่ได้ประกาศฟังก์ชั่น showFullImage ดังนั้น ให้ทำการประกาศฟังก์ชั่นพร้อมรับ paramter เป็น Int ภายในฟังก์ชั่นนี้เราจะทำการสร้าง Dialog และใส่ layout ของ fragment_full_image ลงไป (layout ที่เราสร้างไว้แสดงผลรูปภาพแบบเต็ม พร้อมปุ่มกากบาทสำหรับปิด Dialog)

ในส่วนของ setImageResource อย่าลืมเปลี่ยนเป็น array ของ full image ที่เราประกาศตัวแปรไว้ด้านบนของ class ซึ่งรูป full image ก็จะนำ index เดียวกันกับ preview image มาใช้งานในการเปิดรูป เพื่อนๆจึงจำเป็นต้องเรียงรูป preview กับ full ให้ลำดับตรงกันใน array

ก็เป็นอันเสร็จสำหรับการสร้าง Slideshow แต่ ในตอนนี้สามารถใช้งานได้เฉพาะเมื่อเราแตะลากเองบนหน้าจอเท่านั้น ในลำดับต่อไปเราจะมาทำให้ Slideshow ทำการเปลี่ยนรูปเองอัตโนมัติ

สร้าง timer ให้กับ Slideshow

  1. เรายังอยู่กันในไฟล์ MainActivity.kt ให้สร้างฟังก์ชั่นใหม่ขึ้นมา ถัดจาก showFullImage ในชื่อ ViewPager.autoScroll เป็นการเพิ่มความสามารถให้กับ ViewPager เดิมที่เราใช้งานอยู่ ภายในจะมีลูปการทำงานวนซ้ำๆตามลำดับของรูปที่เปลี่ยนไปตามแต่ละ index ซึ่งฟังก์ชั่นนี้จะรับ parameter เป็น Long จำนวนที่ป้อนเข้ามาอาทิเช่น 3000 จะมีค่าเท่ากับ 3 วินาที ในส่วนถัดมาจะเป็นการดักจับเหตุการณ์ scroll ของรูปภาพบน ViewPager ด้วย override ฟังก์ชั่น

2. ลำดับสุดท้ายให้เลื่อนกลับมาที่ฟังก์ชั่น onCreate ในท้ายฟังก์ชั่นให้ทำการเรียกใช้งาน ViewPager scroll event แล้วระบุจำนวนเวลาที่ต้องการให้ดีเลย์แต่ละภาพลงไป เป็นอันจบการสร้าง Slideshow ด้วย Kotlin แต่เพียงเท่านี้

ทดสอบรันแอ็พบนสมาร์ทโฟน

--

--

No responses yet