flutteranimasiheroMahir3 mnt baca

Hero Animation: Transisi Antar Halaman

Buat gambar produk terbang mulus dari daftar ke detail dengan Hero widget yang simpel.

Efek "terbang" antar halaman

Pernah lihat di aplikasi marketplace: ketuk foto produk di daftar, fotonya membesar terbang ke halaman detail. Itu Hero animation. Flutter menyediakannya hampir gratis lewat widget Hero.

Cara pakai: tag yang sama

Kuncinya adalah dua widget Hero dengan tag yang sama di halaman asal dan tujuan:

dart
// Halaman daftar
ListView.builder(
  itemCount: produk.length,
  itemBuilder: (context, i) {
    final p = produk[i];
    return ListTile(
      leading: Hero(
        tag: 'gambar-${p.id}',
        child: Image.network(p.gambarUrl, width: 56, height: 56, fit: BoxFit.cover),
      ),
      title: Text(p.nama),
      onTap: () => Navigator.push(
        context,
        MaterialPageRoute(builder: (_) => HalamanDetail(produk: p)),
      ),
    );
  },
);

// Halaman detail
class HalamanDetail extends StatelessWidget {
  final Produk produk;
  const HalamanDetail({super.key, required this.produk});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(title: Text(produk.nama)),
      body: Column(
        children: [
          Hero(
            tag: 'gambar-${produk.id}',
            child: Image.network(produk.gambarUrl, height: 280, width: double.infinity, fit: BoxFit.cover),
          ),
          Padding(
            padding: const EdgeInsets.all(16),
            child: Text(produk.nama, style: const TextStyle(fontSize: 22)),
          ),
        ],
      ),
    );
  }
}

Saat navigasi terjadi, Flutter otomatis menganimasikan widget dari posisi dan ukuran asal ke posisi dan ukuran tujuan. Tag harus unik per item, makanya digabung dengan id produk.

Kustomisasi penerbangan

Secara default hero terbang lurus. Kamu bisa mengatur kurva dan perilaku lewat flightShuttleBuilder atau membungkus dengan HeroMode untuk menonaktifkan sementara:

dart
Hero(
  tag: 'gambar-${produk.id}',
  flightShuttleBuilder: (context, anim, direction, fromCtx, toCtx) {
    return ScaleTransition(scale: anim, child: toCtx.widget);
  },
  child: Image.network(produk.gambarUrl),
)

Batasan dan jebakan

Hero bekerja paling baik untuk widget yang secara visual mirip di kedua halaman (biasanya gambar). Jangan memakai Hero untuk teks panjang atau layout kompleks karena hasil morphing-nya bisa aneh. Dan pastikan tag unik: dua Hero dengan tag sama di halaman yang sama menyebabkan error atau animasi ke widget yang salah.

Catatan teknis: Hero animation memakai overlay selama transisi. Kalau halaman tujuan memuat gambar network yang belum ter-cache, hero akan terbang sebagai kotak kosong lalu gambar muncul belakangan, merusak efeknya. Solusinya: precache gambar dengan precacheImage(NetworkImage(url), context) di halaman daftar, atau pakai thumbnail kecil yang sudah dimuat sebagai child Hero.