Animation
การสร้างความเคลื่อนไหวของ UI ใน Flutter — มี 2 แบบหลัก: Implicit (ง่าย) และ Explicit (ควบคุมเอง)
Implicit Animation — ใช้ widget สำเร็จรูป (ง่าย)
Flutter จัดการ animation ให้ — แค่เปลี่ยนค่า widget จะ animate ให้อัตโนมัติ:
// AnimatedSwitcher — animate เมื่อเปลี่ยน child
AnimatedSwitcher(
duration: const Duration(milliseconds: 300),
child: content, // เปลี่ยน child → animate อัตโนมัติ
// สำคัญ: child ต้องมี key ต่างกัน ถึงจะ animate
);
// AnimatedContainer — animate เมื่อ properties เปลี่ยน
AnimatedContainer(
duration: const Duration(milliseconds: 300),
width: isExpanded ? 200 : 100, // เปลี่ยนค่า → animate
height: isExpanded ? 200 : 100,
color: isExpanded ? Colors.blue : Colors.red,
);
// AnimatedOpacity — animate ความโปร่งใส
AnimatedOpacity(
duration: const Duration(milliseconds: 500),
opacity: isVisible ? 1.0 : 0.0,
child: Text('Hello'),
);Implicit Animation Widgets อื่นๆ: AnimatedPadding, AnimatedPositioned, AnimatedDefaultTextStyle
Explicit Animation — สร้าง animation เอง (ควบคุมละเอียด)
ต้องสร้าง AnimationController เอง — ควบคุม timing, direction, repeat ได้:
class _MyWidgetState extends State<MyWidget>
with SingleTickerProviderStateMixin { // ← จำเป็นสำหรับ vsync
late AnimationController _controller;
@override
void initState() {
super.initState();
_controller = AnimationController(
vsync: this, // sync กับ frame rate
duration: const Duration(milliseconds: 300),
lowerBound: 0,
upperBound: 1,
);
_controller.forward(); // เริ่ม animation
}
@override
void dispose() {
_controller.dispose(); // ← ต้อง dispose!
super.dispose();
}
@override
Widget build(BuildContext context) {
return AnimatedBuilder(
animation: _controller,
child: const Icon(Icons.star), // child ไม่ rebuild
builder: (context, child) => SlideTransition(
position: Tween(
begin: const Offset(0, 0.3),
end: const Offset(0, 0),
).animate(CurvedAnimation(
parent: _controller,
curve: Curves.easeInOut,
)),
child: child,
),
);
}
}เมื่อไหร่ใช้ Explicit:
- ต้องการ repeat/reverse animation
- animation ซับซ้อน (ต่อกันหลายจังหวะ)
- ต้องควบคุม timing ละเอียด
Hero Animation — animate ระหว่าง 2 หน้าจอ
widget “บิน” จากหน้าหนึ่งไปอีกหน้า — ใช้ tag เดียวกัน:
// หน้าที่ 1 (list)
Hero(
tag: meal.id, // ← tag ต้องตรงกัน
child: Image.network(meal.imageUrl),
);
// หน้าที่ 2 (detail) — ใช้ tag เดียวกัน
Hero(
tag: meal.id, // ← tag เดียวกัน → Flutter animate ให้
child: Image.network(meal.imageUrl),
);เมื่อ navigate จากหน้า 1 ไปหน้า 2 → Image จะ animate “บิน” จากตำแหน่งเดิมไปตำแหน่งใหม่
เลือกแบบไหนดี
| Implicit | Explicit | Hero | |
|---|---|---|---|
| ความยาก | ง่าย | ซับซ้อน | ง่าย |
| ควบคุม | จำกัด | เต็มที่ | อัตโนมัติ |
| ใช้เมื่อ | เปลี่ยนค่า property | ต้องการ repeat/ควบคุม timing | transition ระหว่างหน้า |
| ตัวอย่าง | ปุ่มเปลี่ยนสี, fade in/out | loading spinner, splash | รูปบินจาก list ไป detail |
Key Points
- เริ่มจาก Implicit ก่อน — ง่ายและเพียงพอสำหรับงานส่วนใหญ่
- Explicit ใช้
AnimationController+SingleTickerProviderStateMixin+ ต้องdispose() Heroใช้tagเดียวกันใน 2 หน้า → Flutter animate transition ให้อัตโนมัติAnimatedSwitcherต้องมีkeyต่างกันบน child ถึงจะ animate
Related
- Flutter — framework ที่รองรับ animation
- Widgets — AnimatedSwitcher, Hero, AnimatedContainer เป็น widgets
- Navigation — Hero animation ทำงานร่วมกับ Navigator