Flutter: GridView
How to create GridView layout
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.
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.
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.
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
.
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),
),
),
),
],
),
);
}
}
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.
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.
Coba kita bandingkan ya.
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.
Sekarang coba kita bandingkan lagi ya.
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.
Sekarang coba kita bandingkan lagi ya.
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.