Flutter: GridView

How to create GridView layout

Yudi Setiawan
Nusanet Developers
7 min readJan 30, 2019

--

Pengenalan

Di Flutter untuk membuat layout secara GridView kita bisa menggunakan widget GridView. Berdasarkan dokumentasinya dituliskan GridView adalah sebagai berikut.

A scrollable, 2D array of widgets. The main axis direction of a grid is the direction in which it scrolls. The most commonly used grid layouts are GridView.count, which creates a layout with a fixed number of tiles in the cross axis, and GridView.extent, which creates a layout with tiles that have a maximum cross axis extent.

Jadi, intinya adalah hampir sama seperti pada Android juga dimana, widget GridView memiliki konsep yang sama yaitu layout yang disusun secara 2 dimensi baik secara horizontal maupun vertikal.

Penggunaan Dasar

Sebagai penggunaan dasarnya kita akan coba buat tampilan seperti berikut.

Penggunaan dasar GridView

Berikut source code-nya.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Container(
color: Colors.yellowAccent,
child: Center(
child: Text("1", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.blueAccent,
child: Center(
child: Text("2", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.brown,
child: Center(
child: Text("3", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.orange,
child: Center(
child: Text("4", style: TextStyle(fontSize: 24.0),),
),
),
],
),
);
}
}

Pada kode diatas, kita ada deklarasikan property nilai crossAxisCount sebanyak 2 dimana ini artinya kita mendeklarasikan berapa jumlah kolom pada GridView tersebut.

GridView Fullscreen

Untuk membuatnya fullscreen coba kita buat kode-nya seperti berikut.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Container(
color: Colors.yellowAccent,
height: double.infinity, // tambahkan property berikut
child: Center(
child: Text("1", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.blueAccent,
height: double.infinity, // tambahkan property berikut
child: Center(
child: Text("2", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.brown,
height: double.infinity, // tambahkan property berikut
child: Center(
child: Text("3", style: TextStyle(fontSize: 24.0),),
),
),
Container(
color: Colors.orange,
height: double.infinity, // tambahkan property berikut
child: Center(
child: Text("4", style: TextStyle(fontSize: 24.0),),
),
),
],
),
);
}
}

Sekarang coba jalankan lagi.

Kok nggak fullscreen ya???

Ada aneh ya 😕 Kita sudah pakai set height pada widget Container menjadi double.infinity namun, kok masih belum fullscreen juga ya. Sekarang coba kita eksperimen dengan cara ganti nilai property height -nya menjadi statik seperti berikut.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: GridView.count(
crossAxisCount: 2,
children: <Widget>[
Container(
color: Colors.yellowAccent,
height: 500.0, // Coba ganti nilai-nya menjadi statik
child: Center(
child: Text(
"1",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.blueAccent,
height: 500.0, // Coba ganti nilai-nya menjadi statik
child: Center(
child: Text(
"2",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.brown,
height: 500.0, // Coba ganti nilai-nya menjadi statik
child: Center(
child: Text(
"3",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.orange,
height: 500.0, // Coba ganti nilai-nya menjadi statik
child: Center(
child: Text(
"4",
style: TextStyle(fontSize: 24.0),
),
),
),
],
),
);
}
}

Sekarang coba jalankan lagi ya.

Kok masih sama ya??? Nggak ada perubahan sama sekali

Hhhhmmmm… 🤔 aneh ya. Kok nggak ada perubahan sama sekali ya. Padahal nilai property height -nya sudah di-set menjadi statik. Sekarang coba kita lihat daftar property yang tersedia di widget GridView .

https://docs.flutter.io/flutter/widgets/GridView/GridView.count.html

Jika kita perhatikan sepertinya ada satu property yang bisa kita pakai untuk membuat item si GridView bisa menjadi fullscreen yakni kita pakai property childAspectRatio dimana jika kita lihat nilai default-nya ialah 1.0 berarti, berapapun size yang kita ubah-ubah diawal tadi ternyata tidak akan berpengaruh karena ratio-nya sendiri sudah ditentukan oleh si GridView -nya. Sekarang, coba kita eksperimen lagi dengan cara ganti nilai property tersebut menjadi 16/9 seperti berikut.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: GridView.count(
crossAxisCount: 2,
childAspectRatio: 16/9, // tambahkan nilai berikut
children: <Widget>[
Container(
color: Colors.yellowAccent,
child: Center(
child: Text(
"1",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.blueAccent,
child: Center(
child: Text(
"2",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.brown,
child: Center(
child: Text(
"3",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.orange,
child: Center(
child: Text(
"4",
style: TextStyle(fontSize: 24.0),
),
),
),
],
),
);
}
}
Ternyata pakai property ini ya.
Yeah…

Karena tekniknya pakai rasio maka, logikanya untuk bisa membuat item GridView-nya bisa fullscreen ialah kita harus mengetahui ukuran width dan height dari layar perangkat kita. Caranya kita bisa pakai MediaQuery dan berikut contoh penggunaannya.

var mediaQueryData = MediaQuery.of(context);
final double widthScreen = mediaQueryData.size.width;
final double heightScreen = mediaQueryData.size.height;

Sekarang coba kita ubah lagi kode sebelumnya biar item GridView-nya bisa fullscreen.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var mediaQueryData = MediaQuery.of(context);
final double widthScreen = mediaQueryData.size.width;
final double heightScreen = mediaQueryData.size.height;

return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: GridView.count(
crossAxisCount: 2,
childAspectRatio: widthScreen/heightScreen, // ubah kode ini
children: <Widget>[
Container(
color: Colors.yellowAccent,
child: Center(
child: Text(
"1",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.blueAccent,
child: Center(
child: Text(
"2",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.brown,
child: Center(
child: Text(
"3",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.orange,
child: Center(
child: Text(
"4",
style: TextStyle(fontSize: 24.0),
),
),
),
],
),
);
}
}

Sekarang coba kita lihat hasilnya.

Yee… sudah fullscreen ya

Yeah… item GridView-nya sudah fullscreen ya. Namun jika kita perhatikan sepertinya item nomor 3 dan 4 kok kayaknya nggak pas gitu ya ukuran height-nya dengan item nomor 1 dan 2. Perhatikanlah baik-baik gambar diatas. 🤔 Penyebabnya adalah karena pada layar diatas kita pakai layar yang ada batas bawahnya (padding) dan AppBar-nya juga nggak kita ikut hitung ukurannya. Jadi, solusinya kita harus mengetahui ukuran dari batas bawah layarnya dan AppBar-nya kemudian, kurangkan nilai height layar kita dengan batas bawah tersebut dan ukuran AppBar-nya.

var mediaQueryData = MediaQuery.of(context);
final double widthScreen = mediaQueryData.size.width;
final double appBarHeight = kToolbarHeight;
final double paddingBottom = mediaQueryData.padding.bottom;
final double heightScreen = mediaQueryData.size.height - paddingBottom - appBarHeight;

Sekarang coba jalankan lagi.

Sudah agak mendingan ya.

Coba kita bandingkan ya.

Sebelah kiri setelah height layar dikurangin dengan AppBar dan batas bawah. Sementara, sebelah kanan height layar tidak dikurangin apapun.

Terlihat jelas kan perbedaannya. Tapi kayaknya masih sedikit kurang pas ya. Kayaknya masih lebih panjang yang item GridView bagian atas dibandingkan item GridView bagian bawahnya. Sekarang, coba kita pakai widget SafeArea dimana widget ini berfungsi untuk memberikan posisi yang aman untuk peletakan widget kita dilayar yang memiliki batas atas dan bawah seperti pada layar diatas.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var mediaQueryData = MediaQuery.of(context);
final double widthScreen = mediaQueryData.size.width;
final double appBarHeight = kToolbarHeight;
final double paddingBottom = mediaQueryData.padding.bottom;
final double heightScreen = mediaQueryData.size.height - paddingBottom - appBarHeight;

return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: SafeArea( // Bungkus GridView dengan ini
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: widthScreen/heightScreen,
children: <Widget>[
Container(
color: Colors.yellowAccent,
child: Center(
child: Text(
"1",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.blueAccent,
child: Center(
child: Text(
"2",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.brown,
child: Center(
child: Text(
"3",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.orange,
child: Center(
child: Text(
"4",
style: TextStyle(fontSize: 24.0),
),
),
),
],
),
),
);
}
}

Sekarang coba lihat lagi hasilnya.

Nah terlihat kan bahwa widget kita ditempatkan di posisi yang aman alias tidak berada di bagian batasnya.

Sekarang coba kita bandingkan lagi ya.

Sebelah kiri dengan SafeArea. Bagian tengah dan kanan tanpa widget SafeArea

Tapi, jika kita perhatikan lagi sepertinya masih ada sedikit lagi kurang-nya ya. Yaitu, kita lupa menghitung batas bagian atas layarnya (padding top). Sekarang coba kita ubah lagi kodenya seperti berikut.

class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
var mediaQueryData = MediaQuery.of(context);
final double widthScreen = mediaQueryData.size.width;
final double appBarHeight = kToolbarHeight;
final double paddingTop = mediaQueryData.padding.top;
final double paddingBottom = mediaQueryData.padding.bottom;
final double heightScreen = mediaQueryData.size.height - paddingBottom - paddingTop - appBarHeight;

return Scaffold(
appBar: AppBar(
title: Text(
"GridView",
style: TextStyle(color: Colors.white),
),
),
body: SafeArea(
child: GridView.count(
crossAxisCount: 2,
childAspectRatio: widthScreen/heightScreen,
children: <Widget>[
Container(
color: Colors.yellowAccent,
child: Center(
child: Text(
"1",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.blueAccent,
child: Center(
child: Text(
"2",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.brown,
child: Center(
child: Text(
"3",
style: TextStyle(fontSize: 24.0),
),
),
),
Container(
color: Colors.orange,
child: Center(
child: Text(
"4",
style: TextStyle(fontSize: 24.0),
),
),
),
],
),
),
);
}
}

Sekarang coba jalankan lagi.

Yeah… dah cocok kan

Sekarang coba kita bandingkan lagi ya.

Yang paling kiri merupakan hasil akhirnya

Kesimpulan

Jadi, kesimpulannya adalah bahwa penggunaan GridView di Flutter saya rasa tidaklah terlalu susah. Dikarenakan Flutter sudah menyediakan banyak widget dan property yang membantu kita untuk lebih mudah membuat rancangan layout-nya.

--

--