วิศวกรรมที่ Sprout: สร้างเครื่องมือเลือกเดือน Android
เผยแพร่แล้ว: 2020-06-26หมายเหตุ: บทความนี้อิงตาม Material Components เวอร์ชัน 1.2.0-beta01 ณ วันที่ 1 มิถุนายน 2020
ในช่วงสามปีครึ่งที่ฉันทำงานในทีม Android เล็กๆ ที่ Sprout Social สิ่งสำคัญอย่างหนึ่งที่กระตุ้นให้ฉันเข้ามาทำงานทุกวันคืออิสรภาพและความไว้วางใจจากบริษัทของเราในการแก้ไขปัญหาในแบบที่เราเห็นว่าดีที่สุด
อิสระในการวิจัยและสำรวจวิธีแก้ปัญหาต่างๆ มากมายสำหรับปัญหาที่เราเห็นว่าจำเป็น ในขณะที่พิจารณากรอบเวลาในการส่งมอบการอัปเดตผลิตภัณฑ์ ช่วยให้เราสามารถค้นหาโซลูชันที่ดีที่สุดสำหรับทั้งลูกค้าและซอฟต์แวร์ของเรา
ความท้าทายประการหนึ่งเกี่ยวข้องกับการสร้างองค์ประกอบ UI สำหรับคุณลักษณะการรายงานบนมือถือใหม่ของเรา องค์ประกอบใหม่นี้คือตัวเลือกหนึ่งเดือน ซึ่งทำให้ผู้ใช้ของเรากำหนดขอบเขตช่วงวันที่สำหรับรายงานการวิเคราะห์ได้
จุดเริ่มต้นที่เราเลือกคือไลบรารีส่วนประกอบวัสดุที่มีอยู่ แทนที่จะเริ่มต้นจากศูนย์ ไลบรารีนี้ได้รับการบำรุงรักษาอย่างจริงจังและสอดคล้องกับข้อกำหนดของวัสดุ ด้วยห้องสมุดนี้เป็นพื้นฐาน เราอาจลดจำนวนตรรกะที่เราต้องเขียนด้วยตัวเอง
ในบทความนี้ ฉันจะอธิบายวิธีที่เราดำเนินการในกระบวนการนี้ ปัจจัยเฉพาะบางอย่างในการสร้างแอป Sprout สำหรับ Android "gotchas" บางส่วนที่เกิดขึ้น (และแก้ไข) ตลอดเส้นทาง และสิ่งที่ต้องทราบหากคุณ ทำงานในโครงการที่คล้ายกัน
บทนำ
ส่วนประกอบวัสดุ Android 1.1.0 เปิดตัวแนะนำองค์ประกอบ UI ตัวเลือกวันที่ใหม่ ฟีเจอร์ใหม่ที่น่ายินดีอย่างหนึ่งของ MaterialDatePicker
ใหม่บน AppCompat CalendarView
คือความสามารถในการเลือกช่วงวันที่โดยใช้มุมมองปฏิทินหรือช่องป้อนข้อความ
AppCompat CalendarView แบบเก่าไม่ยืดหยุ่นมากนัก เป็นองค์ประกอบที่ดีสำหรับกรณีการใช้งานที่จำกัดซึ่งตั้งใจจะแก้ไข นั่นคือ การเลือกวันที่เดียวและวันที่ต่ำสุดและสูงสุดที่ไม่บังคับ เพื่อระบุขอบเขตวันที่ที่อนุญาต
MaterialDatePicker ใหม่สร้างขึ้นด้วยความยืดหยุ่นมากขึ้นเพื่อให้สามารถใช้ฟังก์ชันการทำงานที่เพิ่มขึ้นได้ มันทำงานผ่านชุดของอินเทอร์เฟซที่สามารถนำไปใช้เพื่อปรับแต่งและปรับเปลี่ยนพฤติกรรมของตัวเลือก
การปรับเปลี่ยนลักษณะการทำงานนี้ทำได้ในขณะใช้งานจริงผ่านชุดของฟังก์ชันรูปแบบตัวสร้างบนคลาส MaterialDatePicker.Builder
ซึ่งหมายความว่าเราสามารถขยายพฤติกรรมพื้นฐานของ MaterialDatePicker
นี้ผ่านส่วนประกอบอินเทอร์เฟซที่เขียนได้
หมายเหตุ: แม้ว่า MaterialDatePicker
จะมีส่วนประกอบหลายอย่าง แต่ในบทความนี้ เราจะครอบคลุมเฉพาะส่วนประกอบการเลือกวันที่เท่านั้น
ตัวเลือกช่วงวันที่
ทีมงาน Sprout Social Android กำลังสร้างส่วนรายงาน Analytics
ส่วนใหม่นี้จะอนุญาตให้ผู้ใช้ของเราเลือกชุดตัวกรองและชุดช่วงวันที่ที่รายงานจะครอบคลุม
MaterialDatePicker
มาพร้อมกับส่วนประกอบที่สร้างไว้ล่วงหน้าบางส่วนที่เราสามารถใช้ประโยชน์ได้เพื่อให้กรณีการใช้งานของเราสำเร็จ
สำหรับกรณีทั่วไปของเรา การอนุญาตให้ผู้ใช้เลือกช่วงวันที่ MaterialDatePicker
ที่สร้างไว้ล่วงหน้าก็เพียงพอแล้ว:
ด้วยบล็อกรหัสนี้ เราได้รับตัวเลือกวันที่ที่อนุญาตให้ผู้ใช้เลือกช่วงวันที่
ตัวเลือกวันที่รายเดือน
รายงาน Sprout Social ฉบับหนึ่งที่มีการเลือกวันที่ที่ไม่ซ้ำกันมากขึ้นคือรายงานแนวโน้มของ Twitter
รายงานนี้แตกต่างจากรายงานอื่นๆ ตรงที่แทนที่จะอนุญาตให้ใช้ช่วงวันที่ใดๆ แต่บังคับใช้การเลือกเดือนเดียว ซึ่งหมายความว่าผู้ใช้สามารถเลือกได้เฉพาะเดือนมีนาคม 2020 เทียบกับ 3 มีนาคม ถึง 16 มีนาคม 2020
เว็บแอปของเราจัดการสิ่งนี้โดยใช้ฟิลด์แบบฟอร์มดรอปดาวน์:
MaterialDatePicker
ไม่มีวิธีบังคับใช้ข้อจำกัดดังกล่าวกับตัวเลือกช่วงวันที่ของวัสดุที่สร้างไว้ล่วงหน้าที่กล่าวถึงในส่วนก่อนหน้า โชคดีที่ MaterialDatePicker สร้างขึ้นด้วยชิ้นส่วนที่ประกอบได้ซึ่งช่วยให้เราสามารถขยายการทำงานเริ่มต้นสำหรับกรณีการใช้งานเฉพาะของเราได้
พฤติกรรมการเลือกวันที่
MaterialDatePicker
ใช้ประโยชน์จาก DateSelector
เป็นอินเทอร์เฟซที่ใช้สำหรับตรรกะการเลือกของตัวเลือก
จาก Javadoc:
“อินเทอร์เฟซสำหรับผู้ใช้ {@link MaterialCalendar<S>}
เพื่อควบคุมวิธีที่ปฏิทินแสดงและส่งคืนการเลือก…”
คุณจะสังเกตเห็นว่า MaterialDatePicker.Builder.dateRangePicker()
ส่งคืนอินสแตนซ์ตัวสร้างของ RangeDateSelector
ซึ่งเราใช้ในตัวอย่างข้างต้น
คลาสนี้เป็นตัวเลือกที่สร้างไว้ล่วงหน้าซึ่งใช้งาน DateSelector
ระดมสมองพฤติกรรมการเลือกวันที่รายเดือน
สำหรับกรณีการใช้งานของเรา เราต้องการวิธีให้ผู้ใช้เลือกทั้งเดือนเป็นช่วงวันที่ที่เลือก เช่น พฤษภาคม 2020 เมษายน 2020 เป็นต้น
เราคิดว่า RangeDateSelector
ที่สร้างไว้ล่วงหน้าที่อ้างอิงด้านบนช่วยให้เราไปถึงที่นั่นได้มากที่สุด คอมโพเนนต์อนุญาตให้ผู้ใช้เลือกช่วงวันที่และบังคับใช้ขอบเขต [ล่าง, บน]
สิ่งเดียวที่ขาดหายไปคือวิธีการบังคับใช้การเลือกเพื่อเลือกทั้งเดือนโดยอัตโนมัติ ลักษณะการทำงานเริ่มต้นของ RangeDateSelector
ให้ผู้ใช้เลือกวันที่เริ่มต้นและวันที่สิ้นสุด
เราต้องการพฤติกรรมเพื่อที่ว่าเมื่อผู้ใช้เลือกวันในเดือนนั้น เครื่องมือเลือกจะเลือกทั้งเดือนโดยอัตโนมัติเป็นช่วงวันที่
โซลูชันที่เราตัดสินใจคือขยาย RangeDateSelector
แล้วแทนที่พฤติกรรมการเลือกวันเพื่อเลือกทั้งเดือนโดยอัตโนมัติแทน
โชคดีที่มีฟังก์ชันที่เราสามารถแทนที่ได้จากอินเทอร์เฟซ DateSelector
เรียกว่า: select(selection: Long)
ฟังก์ชันนี้จะถูกเรียกใช้เมื่อผู้ใช้เลือกวันในเครื่องมือเลือก โดยวันที่เลือกผ่านไปในหน่วยมิลลิวินาที UTC จากยุค
การใช้พฤติกรรมการเลือกวันที่รายเดือน
การใช้งานกลายเป็นส่วนที่ง่ายที่สุด เนื่องจากเรามีฟังก์ชันที่ชัดเจน เราจึงสามารถแทนที่เพื่อให้ได้พฤติกรรมที่เราต้องการ
ตรรกะพื้นฐานจะเป็นดังนี้:
- ผู้ใช้เลือกวัน
- ฟังก์ชัน
select()
ถูกเรียกใช้พร้อมกับวันที่เลือกในหน่วยมิลลิวินาทีแบบ ยาว UTC จากยุค - หาวันแรกและวันสุดท้ายของเดือนจากวันที่กำหนดส่งมาถึงเรา
- โทรไปที่
super.select(1st of month)
&super.select(last day of month)
- ลักษณะการทำงานหลักจาก
RangeDateSelector
ควรทำงานตามที่คาดไว้ และเลือกเดือนเป็นช่วงวันที่
วางมันทั้งหมดเข้าด้วยกัน
ตอนนี้เรามี Custom MonthRangeDateSelector
แล้ว เราก็สามารถตั้งค่า MaterialDatePicker
ของเราได้
เพื่อนำตัวอย่างเพิ่มเติม เราสามารถประมวลผลผลลัพธ์ของการเลือกดังนี้:
ผลลัพธ์จะมีลักษณะดังนี้:
Gotchas
มีปัญหาสำคัญเพียงปัญหาเดียวที่ทำให้เข้าถึงแนวทางแก้ไขปัญหานี้ได้ยาก
องค์ประกอบหลักที่ใช้ในการสร้าง MonthRangeDateSelector
ของเราคือคลาส RangeDateSelector
และอินเทอร์เฟซ DateSelector
เวอร์ชันของไลบรารีที่ใช้ในบทความนี้ (1.2.0-beta01) จำกัดการเปิดเผยไฟล์ทั้งสองนี้ เพื่อไม่ให้ขยายหรือนำไปใช้
ด้วยเหตุนี้ แม้ว่าเราจะสามารถคอมไพล์ MonthRangeDateSelector
ใหม่ของเราได้สำเร็จ แต่คอมไพเลอร์ก็แสดงคำเตือนที่น่ากลัวมากเพื่อไม่ให้เราทำเช่นนั้น:
วิธีหนึ่งในการซ่อนคำเตือนคอมไพเลอร์นี้คือการเพิ่ม @Suppress("RestrictedApi")
เช่น:
ประสบการณ์นี้แสดงให้เห็นว่า แม้ว่าไลบรารีส่วนประกอบวัสดุได้มอบส่วนประกอบใหม่ที่ยอดเยี่ยมให้กับชุมชนนักพัฒนา Android แต่ก็ยังอยู่ในระหว่างดำเนินการ
ส่วนที่ดีของห้องสมุดนี้คือการเปิดกว้างเพื่อรับข้อเสนอแนะจากชุมชน Android! หลังจากค้นพบข้อจำกัดการมองเห็นส่วนประกอบนี้ ฉันได้เปิดปัญหาในโปรเจ็กต์ Github และเปิด PR เพื่อจัดการทันที
การวนรอบความคิดเห็นแบบเปิดนี้ระหว่างทีมส่วนประกอบวัสดุและชุมชน Android ทำให้เกิดความร่วมมือและผลลัพธ์ที่ยอดเยี่ยมสำหรับทุกคน
บทสรุป
MaterialDatePicker
ใหม่มีฟังก์ชันการทำงานที่พร้อมใช้งานซึ่งน่าจะครอบคลุมกรณีการใช้งานส่วนใหญ่ในการเลือกวันที่
อย่างไรก็ตาม ส่วนที่ดีที่สุดของมันเหนือบางอย่างเช่น AppCompat CalendarView ก็คือมันถูกสร้างขึ้นในรูปแบบที่ประกอบได้ ดังนั้นจึงสามารถขยายและแก้ไขได้ง่ายสำหรับกรณีการใช้งานเฉพาะ ในขณะที่การทำสิ่งนี้ให้สำเร็จใน CalendarView
จะยากกว่ามาก
ขอขอบคุณเป็นพิเศษ
ฉันต้องการเน้นบางคนที่ช่วยทบทวนบทความนี้:
- นิค เร้าท์ (Github)
- ไมค์ วูลฟ์สัน (Github)
- ไรอัน ฟิลลิปส์ (LinkedIn)
- ลูคัส โมลเลอร์ (Github)
- มิต พาเทล (LinkedIn)