gridviewgridlayoutMenengah4 mnt baca

GridView.builder

Tata letak grid efisien untuk galeri dan katalog produk.

Kapan Memakai Grid

Grid adalah jawaban ketika item-itemmu setara dan paling enak dilihat berdampingan: galeri foto, katalog produk, menu dashboard, atau pilihan avatar. Seperti ListView.builder, GridView.builder juga lazy: ia hanya membangun sel yang sedang terlihat di layar, jadi ribuan item pun tetap ringan.

Satu-satunya hal baru yang perlu kamu pahami adalah gridDelegate, si pengatur tata letak yang menentukan berapa kolom dan seberapa besar tiap sel.

Contoh 1: Katalog Produk 2 Kolom

dart
GridView.builder(
  padding: const EdgeInsets.all(12),
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 2,
    crossAxisSpacing: 12,
    mainAxisSpacing: 12,
    childAspectRatio: 3 / 4,
  ),
  itemCount: produk.length,
  itemBuilder: (context, index) {
    final p = produk[index];
    return Card(
      clipBehavior: Clip.antiAlias,
      child: Column(
        crossAxisAlignment: CrossAxisAlignment.stretch,
        children: [
          Expanded(
            child: Image.network(p.gambar, fit: BoxFit.cover),
          ),
          Padding(
            padding: const EdgeInsets.all(8),
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              children: [
                Text(p.nama, maxLines: 1, overflow: TextOverflow.ellipsis),
                Text(
                  formatRupiah(p.harga),
                  style: const TextStyle(fontWeight: FontWeight.bold),
                ),
              ],
            ),
          ),
        ],
      ),
    );
  },
)

childAspectRatio: 3 / 4 berarti rasio lebar:tinggi tiap sel adalah 3 banding 4, jadi sel lebih tinggi daripada lebarnya, cocok untuk kartu produk vertikal. maxLines: 1 dengan ellipsis mencegah nama produk yang panjang merusak layout.

Contoh 2: Galeri Foto dengan Status Loading

Untuk gambar dari internet, selalu tangani tiga kondisi: sedang dimuat, berhasil, dan gagal.

dart
GridView.builder(
  padding: const EdgeInsets.all(12),
  gridDelegate: const SliverGridDelegateWithFixedCrossAxisCount(
    crossAxisCount: 3,
    crossAxisSpacing: 8,
    mainAxisSpacing: 8,
  ),
  itemCount: foto.length,
  itemBuilder: (context, index) => ClipRRect(
    borderRadius: BorderRadius.circular(8),
    child: Image.network(
      foto[index],
      fit: BoxFit.cover,
      loadingBuilder: (context, child, progress) {
        if (progress == null) return child;
        return const Center(child: CircularProgressIndicator());
      },
      errorBuilder: (context, error, stackTrace) {
        return const ColoredBox(
          color: Colors.black12,
          child: Icon(Icons.broken_image, color: Colors.grey),
        );
      },
    ),
  ),
)

Tanpa loadingBuilder, sel akan kosong melompong saat gambar diunduh dan grid terlihat berkedip. Tanpa errorBuilder, satu URL rusak bisa menampilkan kotak merah error yang merusak seluruh galeri.

Edge Cases

  • Teks overflow di dalam sel: karena tinggi sel ditentukan oleh rasio, teks yang kepanjangan akan overflow (garis kuning-hitam). Solusinya: maxLines + TextOverflow.ellipsis, atau FittedBox untuk teks yang harus selalu muat satu baris.
  • Grid di dalam halaman scroll lain: misalnya grid produk di bawah header dalam SingleChildScrollView. Kamu butuh shrinkWrap: true dan physics: const NeverScrollableScrollPhysics(). Tapi ingat, ini mematikan lazy loading: seluruh item dibangun sekaligus. Untuk data besar, pakai CustomScrollView + SliverGrid agar tetap lazy.
  • childAspectRatio adalah lebar dibagi tinggi. Nilai di atas 1 berarti sel melebar, di bawah 1 berarti sel meninggi. Mudah tertukar, jadi selalu baca ulang saat layout terlihat aneh.

Kapan JANGAN Memakai GridView.builder

  • Item sedikit dan statis (kurang dari 10, misalnya menu dashboard tetap): GridView.count lebih ringkas karena tidak butuh itemBuilder.
  • Ukuran sel bervariasi (grid ala Pinterest): grid bawaan selalu seragam per baris. Pakai MasonryGridView dari package flutter_staggered_grid_view.
  • Grid hanya sebagian kecil halaman scroll kompleks (header + grid + footer): pakai SliverGrid di dalam CustomScrollView agar semua tetap lazy dalam satu scroll.

Praktik Terbaik

  • Beri Key pada item yang stateful (misalnya kartu dengan tombol favorit) supaya state tidak tertukar saat list di-scroll atau data berubah.
  • Hindari widget mahal di tiap sel (bayangan tebal, BackdropFilter, blur) untuk grid panjang: puluhan blur yang dirender bersamaan bisa menurunkan frame rate.
  • Selalu beri padding di grid, bukan margin di tiap item: lebih konsisten dan tidak menggandakan jarak di tepi.

Catatan teknis: Butuh jumlah kolom yang menyesuaikan lebar layar (2 di HP, 4 di tablet)? Itu tugas SliverGridDelegateWithMaxCrossAxisExtent, dibahas di modul berikutnya.

Tantangan

Katalog 2 kolom

Buat GridView 2 kolom berisi 6 kartu produk (nama 'Produk 1'..'Produk 6'), dengan jarak 12 dan rasio 3/4.