ประสบการณ์ ความท้าทาย ในการสร้าง Category Filter ที่สามารถย่อ/ขยายได้ บนแอป LINE MAN

Nuntapong Aoumrod
Life@LINE MAN Wongnai
5 min readMay 30, 2023

--

ก่อนจะเข้าเนื้อหา ผมขอแนะนำตัวกับผู้อ่านทุกท่านนะครับ ผมชื่อนันทพงศ์ อ่วมรอด ชื่อเล่นต้นไม้ ปัจจุบันเป็น Junior Android Developer ของทีม Podong/Search squad ซึ่งเป็นทีมที่พัฒนาและดูแลเกี่ยวกับ ระบบการค้นหาร้านอาหารและการแสดงผลรายการร้านอาหารบนแอป LINE MAN โดยในวันนี้ผมจะมาเล่าเกี่ยวกับ ประสบการณ์การสร้าง Category Filter แบบใหม่ ที่สามารถย่อ/ขยายได้ ในหน้ารายการร้านอาหารครับ

หน้ารายการร้านอาหาร

เมื่อเราต้องการที่จะสั่งอาหารบนแอป​ LINE MAN เราจะสามารถเข้ามายังหน้ารายการร้านอาหารได้ จากการกดที่ปุ่ม Food Delivery และกดเลือกหมวดของร้านอาหารที่เราสนใจ แบบนี้

โดยเมื่อเราเข้ามาในหน้ารายการร้านอาหารแล้ว เราก็จะพบกับ รายการร้านอาหารที่มีให้เลือกจำนวนมาก จนอาจทำให้เราต้องใช้เวลานานในการเลื่อนหาร้านที่เราถูกใจ (เพราะว่าเรามีร้านอาหารมากมายทั่วประเทศไทย ที่ร่วมกับ LINE MAN ให้คุณเลือก ><)

General Filter และ Category Filter

เพื่อที่จะช่วยลดเวลา ในการเลื่อนหาร้านอาหาร เราจึงออกแบบให้หน้าแสดงรายการร้านอาหาร มีฟังก์ชันที่สามารถจะคัดกรองร้านอาหารที่เราสนใจได้อย่างรวดเร็ว จากข้อมูลต่าง ๆ ที่ร้านระบุไว้ เช่น

  • สถานะ เปิด/ปิด
  • ช่วงราคาของอาหารในร้าน
  • การเข้าร่วมโปรโมชัน
  • ประเภทของร้านอาหาร (Category Filter)
  • อื่น ๆ

General Filter และ Category Filter แบบใหม่

โดยหลังจากผ่านมาช่วงเวลาหนึ่ง ทางพี่ ๆ ทีมดีไซน์เนอร์ มีความต้องการที่อยากจะออกแบบ General Filter และ Category Filter ใหม่ เพื่อให้สอดคล้องกับ Design System ของแอป LINE MAN และเพิ่มความสามารถในการย่อ/ขยายพื้นที่ให้กับ Category Filter ในขณะที่ผู้ใช้กำลังเลื่อนดูรายการร้านอาหาร

ทำไมเราต้องย่อ/ขยาย Category Filter?

ภาพ UI ของ Category Filter พี่ทีมดีไซน์เนอร์ออกแบบมา

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

ดังนั้น การออกแบบให้ Category Filter สามารถย่อพื้นที่ลงได้ ในขณะที่ผู้ใช้เลื่อนดูรายการร้านอาหาร จะสามารถช่วยเพิ่มพื้นที่ในการมองเห็นรายการร้านอาหารได้อย่างมาก ในอีกมุมหนึ่ง เมื่อผู้ใช้ไม่ต้องการเลื่อนดูรายการร้านอาหารแล้ว การขยาย Category Filter ขึ้น จะช่วยให้ผู้ใช้สามารถที่จะเลือกประเภทของร้านอาหารอื่น ๆ ได้อย่างรวดเร็ว

สร้าง Category Filter ในหน้ารายการร้านอาหาร

เราลองมาดูกันว่า โครงสร้างของหน้ารายการร้านอาหารในปัจจุบันเป็นอย่างไร

จากภาพจะเห็นว่า หน้าร้ายการร้านอาหารประกอบไปด้วย Toolbar, Address bar, General Filter และ Restaurant List ตามลำดับ ซึ่ง XML Layout ของหน้ารายการร้านอาหาร ปัจจุบันคือแบบนี้

Toolbar
CoordinatorLayout
Appbar
AddressBar
GeneralFilterBar
RestaurantList

โดยที่ผลลัพธ์ของ UI ที่พี่ ๆ ดีไซน์เนอร์ต้องการจะเป็นแบบนี้

จากผลลัพธ์ของ UI ที่พี่ ๆ ดีไซน์เนอร์ต้องการ ผมจึงได้เพิ่ม Android RecyclerView ลงไปใน XML Layout ของหน้ารายการร้านอาหาร เพื่อใช้สำหรับสร้าง Category Filter แบบนี้

Toolbar
CoordinatorLayout
Appbar
AddressBar
GeneralFilterBar
+ CategoryFilter (Android RecyclerView)
RestaurantList

และสร้าง CategoryFilterAdapter ที่ใช้สำหรับสร้างและกำหนดรายละเอียดให้กับ Item แต่ละชิ้น แบบนี้

CategoryFilterAdapter {
onCreateViewHolder()
onBindViewHolder()
getItemCount()
}

จากนั้น มาลองดูในส่วน UI ของ Item แต่ละชิ้น ที่พี่ ๆ ทีมดีไซน์เนอร์ออกแบบไว้ จะเป็นแบบนี้

ซึ่งเมื่อเราสร้าง XML Layout จะมีโครงสร้างแบบนี้

CategoryImage 
CategoryTitle
Divider

และเมื่อนำ Category Filter (RecyclerView), CategoryFilterAdapter และ Item แต่ละชิ้น มาประกอบรวมกัน บนหน้ารายการร้านอาหาร จะได้ผลลัพธ์แบบนี้

จากผลลัพธ์จะสังเกตว่า Category Filter ได้ถูกสร้างเพิ่มเข้าไปในหน้ารายการร้านอาหารแล้ว แต่ Category Filter ยังไม่สามารถที่จะทำการย่อ/ขยายพื้นที่ได้

วิธีการย่อ/ขยายพื้นที่ของ Category Filter และ Item แต่ละชิ้น

หลังจากที่เราได้สร้าง Category Filter แล้ว เราลองมาดูวิธีที่ทำให้ Category Filter และ Item แต่ละชิ้นด้านใน สามารถย่อ/ขยายพื้นที่ได้กันครับ

โดยส่วนแรก ผมได้ลองปรึกษาพี่ ๆ ในทีมแอนดรอยเกี่ยวกับ การหาวิธีในการย่อ/ขยายพื้นที่ของ Category Filter ซึ่งจากคำแนะนำของพี่ ๆ ในทีม ทำให้ผมได้รู้จักกับ Motion Layout

Motion Layout คืออะไร
คำจัดกัดความง่าย ๆ ของ Motion Layout คือ view ที่สามารถกำหนด อนิเมชัน ให้กับ child view ได้ เช่น การสั่งให้ child view เคลื่อนไหว, ย่อ/ขยายขนาด, หมุน, อื่น ๆ แบบในภาพ

สำหรับคนที่ไม่เคยรู้จักกับ Motion Layout สามารถอ่านเพิ่มเติมได้ที่:
https://developer.android.com/develop/ui/views/animations/motionlayout

วิธีการย่อ/ขยายความสูงของ Category Filter

หลังจากได้ศึกษาความสามารถของ Motion Layout แล้ว ผมจึงได้นำ Motion Layout มาใช้ครอบ Category Fitler ไว้ เพื่อกำหนดอนิเมชันในการย่อ/ขยายความสูงของ Category Fitler ซึ่งทำให้ โครงสร้าง XML Layout เป็นแบบนี้

Toolbar
CoordinatorLayout
Appbar
AddressBar
GeneralFilter
+ MotionLayout
CategoryFilter
RestaurantList

และจากคำแนะนำเพิ่มเติมของพี่ ๆ ทีมแอนดรอย ผมจึงได้ออกแบบให้ Motion Layout ทำการเล่นอนิเมชันเพื่อย่อ/ขยายความสูงของ Category Filter เมื่อ Address bar ถูกดัน จากการเลื่อน Restaurant List (ด้วยความสามารถของ Coordinator Layout)

Coordinator Layout คืออะไร
คำจัดกัดความของ Coodinator Layout คือ view ที่สามารถควบคุมความสัมพันธ์ ของค่า coordinate ระหว่าง child view แต่ละชิ้นได้

ตัวอย่างการนำ Coordinator Layout มาใช้ คือ การดันส่วนหัวเรื่องขึ้น เมื่อทำการเลื่อนเนื้อหา โดยใช้ค่า coordinate ในการอ้างอิงตำแหน่งของการเลื่อน ระหว่าง child view

ซึ่งในหน้ารายการร้านอาหารปัจจุบัน ได้มีการนำความสามารถดังกล่าว มาใช้ในการดัน Address bar ขึ้น/ลง เมื่อมีการเลื่อน รายการร้านอาหาร แบบนี้

ทราบระยะทางการถูกดันของ Address bar จาก Appbar
จากโครงร้าง XML Layout ของหน้ารายการร้านอาหารปัจจุบัน จะพบว่า เราใช้ Appbar ครอบ Address bar ไว้ แบบนี้

Toolbar
CoordinatorLayout
Appbar
AddressBar
GeneralFilter
MotionLayout
CategoryFilter
RestaurantList

โดยเราจะสามารถทราบ ระยะทางที่ Address bar ถูกดัน ได้จากการเพิ่ม callback function ที่ชื่อว่า addOnOffsetChangedListener ให้กับ Appbar

ซึ่ง callback function addOnOffsetChangedListener จะทำงานเมื่อ Address bar ถูกดัน จากการเลื่อน Restaurant List (ด้วยความสามารถของ Coordinate Layout)

และในขณะที่ addOnOffsetChangedListener ทำงาน ผมได้กำหนดให้ Motion Layout เล่นอนิเมชันในการย่อ/ขยายความสูงของ Category Filter จากค่าของระยะทางที่ Address bar ถูกดัน

ดังนั้น ในตอนนี้เราสามารถทำให้ Category Filter ย่อ/ขยายความสูงได้แล้ว จากการเลื่อน Restaurant List

การย่อ/ขยายความสูงและความกว้างของ Item แต่ละชิ้น

หลังจากที่เราสามารถย่อ/ขยายความสูงของ Category Filter ได้แล้ว เราจำเป็นที่จะต้องย่อ/ขยายความสูงของ Item ด้านในแต่ละชิ้นด้วย ดังนั้น เพื่อที่จะสามารถปรับความสูง และความกว้างของ Item แต่ละชิ้นได้ ผมจึงกำหนดสิ่งต่าง ๆ ดังนี้

ในส่วนของการปรับความสูงของ Item แต่ละชิ้น ผมกำหนดให้ Item แต่ละชิ้น มีความสูงเท่ากับ Category Filter เสมอ ซึ่งแปลว่าความสูงของ Category Filter และ Item แต่ละชิ้น จะถูกปรับให้เท่ากันตลอดเวลา

และในส่วนความกว้างของ Item แต่ละชิ้น ผมใช้วิธีการกำหนดอัตราส่วนที่สัมพันธ์กับความสูงปัจจุบัน ดังนั้น ในขณะที่ความสูงของ Item กำลังถูกปรับ ความกว้างก็จะถูกปรับตามด้วยอัตราส่วนที่กำหนดไว้

ซึ่งหลังจากเราได้กำหนด การย่อ/ขยายพื้นที่ของ Category Filter และ Item แต่ละชิ้นแล้ว เราจะได้ผลลัพธ์แบบนี้

จากผลลัพธ์จะเห็นว่า พื้นที่ของ Category Filter และ Item แต่ละชิ้น ถูกปรับให้สามารถย่อ/ขยายได้ เมื่อเราทำการเลื่อน Restaurant List

แต่ถ้าหากสังเกต ในส่วนของเนื้อหาด้านใน Item แต่ละชิ้นตอนนี้ จะพบว่า เนื้อหาด้านในยังไม่ถูกปรับตามพื้นที่ของ Category Filter ที่ลดลง

การอัพเดทเนื้อหาของ Item แต่ละชิ้น

เพื่อที่จะสามารถอัพเดทเนื้อหาของ Item แต่ละชิ้นตามพื้นที่ของ Category Filter และ Item แต่ละชิ้นที่ถูกย่อ/ขยาย ผมจึงได้เพิ่ม Motion Layout ลงไปใน XML Layout ของ Item เพื่อใช้ครอบ CategoryImage, CategoryTitle และ Divider ไว้แบบนี้

+ MotionLayout
CategoryImage
CategoryTitle
Divider

จากนั้นผมจะทำการกำหนด callback function ที่ชื่อว่า addOnLayoutChangeListener ให้กับ Item ไว้

โดยที่ addOnLayoutChangeListener จะทำงานเมื่อ Layout ของ Item ถูกวาดใหม่ จากการปรับความสูงตาม Category Filter

และในขณะที่ addOnLayoutChangeListener กำลังทำงาน ผมได้กำหนดให้ Motion Layout ของ Item แต่ละชิ้น ทำการเล่นอนิเมชัน เพื่อสั่งให้ปรับเนื้อหาของ Item จากค่าระยะทางของ Address bar ที่ถูกดันก่อนหน้านี้ ซึ่งจะได้ผลลัพธ์ที่เราต้องการ แบบในภาพด้านล่าง

สุดท้ายนี้ ผมได้นำความรู้พื้นฐานต่าง ๆ อย่างการใช้ RecyclerView, Motion Layout และ Coordinator Layout มาใช้สร้าง Category Filter ในหน้ารายการร้านอาหาร ซึ่งช่วยให้ผู้ใช้สามารถที่จะคัดกรองรายการร้านอาหาร จากประเภทของร้าน ได้อย่างรวดเร็ว อีกทั้งยังใส่ความสามารถ ในการย่อ/ขยาย เพื่อช่วยเพิ่มพื้นที่ในการมองเห็นรายการร้านอาหารของผู้ใช้ให้มากขึ้น

ซึ่งผมหวังว่าฟีเจอร์ใหม่ชิ้นนี้ จะช่วยสร้างอิมแพคเล็ก ๆ และเพิ่มประสบการณ์ที่ดี ในการคัดกรองหาร้านอาหาร ให้กับผู้ใช้แอปพลิเคชัน LINE MAN นะครับ ><

บทความนี้ เป็นบทความแรกที่ผมเขียน ขอบคุณทุกคนที่เข้ามาอ่านมาก ๆ นะครับ และขอขอบคุณทีม Android LMWN รวมถึงทุก ๆ คน ที่มีส่วนในการช่วยสนับสนุน ให้งานสร้าง Category Filter ชิ้นนี้สำเร็จลุล่วงด้วยครับ

--

--