Flutter | มาลองทำแอป Icon Showcase || Part Extra Bloc+Animation

Suppachai Thanrukprasert
3 min readJan 9, 2020

--

กลับมาอีกรอบกับ Icon Showcase โดยรอบนี้เราจะมาลองเพิ่มการจัดการข้อมูลแบบ BloC กับ อนิเมชั่น เข้ามาในแอปของเรา จึงตั้งโจทย์ไว้ว่า เราจะสามารถเพิ่มลด Icon ใน List ของเราได้ โดยจัดการข้อมูลเหล่านี้ด้วย BloC และเมื่อเพิ่มหรือลบ Icon ออกไปจะมีอนิเมชั่นการเพิ่มหรือลบออกไปด้วย เป็น Scale กับ Fade แบบง่ายๆ นอกเหนือจากนั้นแอปเรายังสามารถทำงานได้เหมือนก่อนหน้า

ในงานนี้ เราก็จะมาแนะนำ ให้รู้จัก 2 อย่าง

  • Flutter Bloc
  • AnimatedList

เราจะเอาโค๊ดเก่ามาต่อยอด สามารถโหลดได้จากข้างล่างเลย

หรืออยากกลับไปอ่านในพาร์ทก่อนหน้าก็กดลิงค์ข้างล่างได้

ถ้าพร้อมแล้วก็ไปกันต่อเลย

⚠️⚠️⚠️ (อัพเดท 8/7/2020) ถ้าใครใช้ flutter_bloc เวอร์ชั่นตั้งแต่ 1.0.0 ขึ้นไป จะมีการเปลี่ยนชื่อ Api บางส่วนดังนี้

bloc.state.listen -> bloc.listen
bloc.currentState -> bloc.state
bloc.dispatch -> bloc.add
bloc.dispose -> bloc.close

สามารถอ่านเพิ่มเติมได้จาก https://link.medium.com/qnfMcEcW00

ดังนั้นตอนทำตาม อาจใช้เวอร์ชั่นที่ระบุไว้ไปก่อนได้ หลักการทำงานของ flutter_bloc ยังเหมือนเดิม

เรามาดูในส่วนของ Bloc ก่อน

หรือว่าอีกอย่างคือ มาสร้างวิธีจัดการกับข้อมูล

สร้างโฟลเดอร์ใหม่ชื่อ bloc

Event

สร้างไฟล์ไว้จัดการ event bloc/iconlist_event.dart

event ของเรามีเพียง 3 อย่าง คือ โหลดค่าตั้งต้น(LoadDefaultIcon) เพิ่ม item(AddIcon) และ ลบ item(RemoveIcon)

iconlist_event.dart

LoadDefaultIcon กับ AddIcon เราไม่จำเป็นต้องรับพารามีเตอร์เข้ามาเพราะเราจะสุ่มเอา ส่วน RemoveIcon จะรับตำแหน่งที่จะลบออก(เพื่อความไม่ซับซ้อน ตำแหน่งที่จะลบ จะลบอันสุดท้ายเสมอ)

State

สร้างไฟล์ไว้จัดการ state ที่จะใช้ส่งไปโชว์ในแอป bloc/iconlist_state.dart

state เราจะมี 2 สถานะ คือ กำลังโหลด(IconListLoaded) กับ โหลดเสร็จแล้ว(IconListLoading)

iconlist_state.dart

IconListLoaded จะสามารถส่งข้อมูล Icon List ได้ ส่วน IconListLoading ไม่จำเป็นต้องส่งข้อมูล ใช้เพื่อบอกสถานะว่ากำลังโหลดข้อมูล

Bloc

เรามาทางเชื่อมระหว่าง event ไป state ด้วย bloc

สร้างไฟล์ใหม่ bloc/iconlist_bloc.dart

เนื่องจากเรามี event 3 อัน เราเลยมีฟังก์ชั่น 3 อันที่จะเชื่อมไป State ทั้ง 2

iconlist_bloc.dart

ฟังก์ชั่นทั้ง 3 อัน ได้แก่

  • _mapAddIconToState() จะทำหน้าที่ สุ่มไอคอนแล้วเพิ่มเข้าไปใน Icon List
  • _mapRemoveIconToState(RemoveIcon event) จะรับตำแหน่งที่จะลบ แล้วลบออกไปจาก Icon List
  • _mapLoadDefaultIconToState() จะโหลดค่าตั้งต้นของ Icon List

รวบไฟล์ export

ตอนนี้ bloc เราครบแล้ว ตั้งแต่ event state bloc เพื่อความง่ายในการเรียกใช้ ก็รวบลง อีกไฟล์นึง แล้ว export เอา จะได้ import เข้ามาไฟล์เดียวได้

สร้างไฟล์ใหม่ชื่อ bloc/iconlist.dart

iconlist.dart

มาทำส่วนดีไซน์กับอนิเมชั่นต่อ

จากโค๊ดเก่า เราเพิ่มมา 2 ปุ่ม เป็น FloatingActionButton ที่มีปุ่ม + กับ ปุ่ม -

เราไปดูโค๊ดใหม่ที่แก้ไขทุกอย่างแล้วเลยดีกว่า

main.dart

มาค่อยๆดูไปทีละส่วนกัน

ตรงนี้เพราะเราใช้ Bloc เลยหุ้ม Widget ที่อยู่นอกสุดด้วย BlocProvider แล้วส่ง builder เป็น IconlistBloc() หรือ Bloc ที่เราพึ่งสร้างไป และเมื่อรันครั้งแรกที่เปิดแอป เราก็จะสั่งให้มันโหลดค่าตั้งต้น dispatch(LoadDefaultIcon())

เราเพิ่ม _listKey ไว้ใช้กับ AnimatedList

เราเพิ่มตัวแปร iconListBloc ไว้เรียก Bloc ของเรา แล้วตอนจะสร้าง Widget เราก็หุ้มไว้ด้วย BlocBuilder ที่ bloc ส่ง iconListBloc ส่วนที่ builder จะส่งฟังก์ชั่นที่สร้าง Widget ในนั้นเราก็เช็คได้ว่า เป็น State ไหน ถ้าเป็น IconListLoading เราจะโชว์ Container() เปล่าๆ (ถ้าใครจะทำจริงจัง ก็เปลี่ยนเป็นไอคอน Loading ได้) แต่ถ้าเป็น IconListLoaded จะโชว์แอปที่เราสร้างมาก่อนหน้า

เปลี่ยนจาก ListView.builder ไปใช้ AnimatedList แทน

เพื่อความเรียบร้อย และจะได้เรียกใช้ซ้ำได้ เราเอา card ของเราไปสร้างเป็นฟังก์ชั่น buildCard ซึ่งจะทำหน้าที่ return Card แล้วได้ผลลัพธ์เหมือนเดิม

ฟังก์ชั่น buildCard

เนื่องจากเป็นอนิเมชั่น เราก็เพิ่ม FadeTransition และ SizeTransition เข้าไปด้วย

ในส่วนนี้เราเพิ่มปุ่ม + และ - วางตรงกลางล่างของแอปตอนกด เราก็จะเรียก event ที่ bloc และ อัพเดท _listKey สำหรับ + _listKey เราจะเพิ่มแค่ตำแหน่งที่จะแทรกเข้า ส่วน - _listKey เราจะลบออกตามตำแหน่งที่ต้องการ นอกจากนั้นต้องส่งฟังก์ชั่นที่สร้าง Card ด้วย (buildCard) นอกจากนี้อย่าลืมตั้ง heroTag ของ FloatingActionButton ให้ต่างกันด้วย เพราะค่าตั้งต้นจะถูกตั้งให้เหมือนกัน

เพียงเท่านี้ แอปก็ออกมาเรียบร้อยแล้ว

ใครมีคำถามสงสัย ก็ส่งทิ้งไว้ข้างล่างได้เช่นเคย ไว้เจอกันใหม่ในครั้งหน้า

ใครอยากดูโค๊ดเต็มแล้ว โหลดได้จากข้างล่างเลย

--

--