Animasi Implisit: AnimatedContainer dan Temannya
Buat animasi halus tanpa AnimationController dengan AnimatedContainer, AnimatedOpacity, dan AnimatedCrossFade.
Animasi tanpa ribet
Animasi implisit adalah cara termudah membuat gerakan halus: kamu cukup mengubah nilai properti, Flutter menganimasikan perubahannya otomatis selama duration. Tidak perlu controller, tween, atau listener.
AnimatedContainer
class KotakAjaib extends StatefulWidget {
const KotakAjaib({super.key});
@override
State<KotakAjaib> createState() => _KotakAjaibState();
}
class _KotakAjaibState extends State<KotakAjaib> {
bool _membesar = false;
@override
Widget build(BuildContext context) {
return Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
AnimatedContainer(
duration: const Duration(milliseconds: 400),
curve: Curves.easeInOut,
width: _membesar ? 200 : 100,
height: _membesar ? 200 : 100,
decoration: BoxDecoration(
color: _membesar ? Colors.teal : Colors.amber,
borderRadius: BorderRadius.circular(_membesar ? 100 : 12),
),
),
const SizedBox(height: 16),
ElevatedButton(
onPressed: () => setState(() => _membesar = !_membesar),
child: const Text('Ubah'),
),
],
);
}
}Satu setState mengubah width, height, warna, dan radius, semuanya teranimasi mulus. curve mengatur easing, Curves.easeInOut memberi kesan natural.
AnimatedOpacity dan AnimatedCrossFade
Untuk fade in/out pakai AnimatedOpacity:
AnimatedOpacity(
duration: const Duration(milliseconds: 300),
opacity: _terlihat ? 1.0 : 0.0,
child: const Text('Halo!'),
)Untuk bertukar dua widget dengan animasi ukuran plus fade, pakai AnimatedCrossFade:
AnimatedCrossFade(
duration: const Duration(milliseconds: 300),
crossFadeState: _login
? CrossFadeState.showFirst
: CrossFadeState.showSecond,
firstChild: const FormLogin(),
secondChild: const FormDaftar(),
)Ini pola bagus untuk toggle login/daftar tanpa pindah halaman.
AnimatedPadding dan AnimatedPositioned
Ada juga AnimatedPadding untuk padding dan AnimatedPositioned (khusus di dalam Stack) untuk posisi. Prinsipnya sama: ubah nilai, beri duration, biarkan Flutter yang menganimasikan.
Batasan animasi implisit
Animasi implisit cocok untuk perubahan properti sederhana yang dipicu state boolean. Untuk urutan animasi kompleks (misalnya staggered, berulang, atau dikontrol gesture), kamu butuh animasi eksplisit dengan AnimationController. Jangan memaksa animasi implisit untuk koreografi rumit, hasilnya akan kaku dan kodenya berantakan.
Catatan teknis: Animasi implisit me-rebuild widget setiap frame selama durasi animasi. Jangan menaruh widget berat (misalnya list panjang atau gambar besar) di dalam AnimatedContainer yang sering berubah, karena setiap frame me-layout ulang semuanya. Pisahkan bagian yang beranimasi dari konten berat, atau pakai
RepaintBoundaryuntuk mengisolasi repaint.