Tutorial List View Flutter — Memisahkan Konten dengan Class Baru

Tutorial List View Flutter dengan memisahkan konten menggunakan class baru

Jeremia Manogi Mario
Komunitas Android  CCIT-FTUI
7 min readDec 5, 2019

--

Kembali dari tutorial sebelumnya. Pada bagian biodata, kita liat untuk bagian yang sedikit saja perlu panjang sekali code yang dibutuhkan. Sekarang kalian sudah tau salah satu kelemahan flutter. Yaitu, penulisan yang sangat panjang. Tapi kita bisa memendekkannya dengan menggunakan beberapa cara. Dan kita akan menggunakan project kemarin sebagai implementasinya.

Buka kembali project login kalian sebelumnya. Sekarang, buat file baru bernama biodata.dart. Jika kalian selalu mengikuti series ini, kalian sudah tau caranya. Oke kita mulai dari menggunakan Constructor.

Menggunakan Constructor

Kita tau cara menggunakan Constructor, seperti ini.

Singkatnya, kita butuh mengisi parameter tersebut untuk memanggilnya. Seperti ini.

Dan akan terus menunjukkan error jika parameter tersebut belum terpenuhi.

Tapi Bagaimana jika hanya beberapa parameter saja yang kita butuhkan, sedangkan sisanya opsional? Kita bisa menutup parameter yang ingin kita jadikan opsional dengan menggunakan kurung siku dan kurung kurawa.

Apa perbedaan dengan menggunakan kurung siku dengan kurung kurawa?

dengan kurung siku

Jika kita menggunakan kurung siku pada parameter/beberapa parameter, kita menjadikan parameter menjadi opsional. Jadi, kita tidak perlu mengisinya juga tidak masalah.

Seperti pada contoh gambar. Pada contoh, ada 5 parameter yang dideklarasikan. Dan ketika memanggilnya, hanya menuliskan 3 input. Tapi tidak error. Dan jika kita ingin mengisi parameter tersebut, isi saja seperti biasa.

Bagaimana dengan kurung kurawa? Sama saja. Hanya cara memanggilnya nanti yang akan berbeda.

dengan kurung kurawa

Sama halnya dengan kurung siku, kita tidak akan mendapatkan “garis merah” a.k.a error, jika kita hanya mengisi 3 parameter. Tapi, jika kita ingin mengisi parameter opsional tersebut, kita harus memanggil nama parameternya seperti di contoh ini:

Sebagai catatan, kalian tidak akan bisa menaruh kurung siku, dan kurung kurawa di depan parameter yang “diprioritaskan”. Jika kalian melakukannya, kalian akan mendapatkan error.

Kenapa kita akan menggunakan constructor di class dan stateless widget yang berbeda ? Kenapa kita akan menggunakan 2 kelas? Kelas pertama akan digunakan untuk menata Widgetnya dengan kelas statless, dan kelas ke-2 akan digunakan untuk menempatkan “custom” widget yang akan kita pakai, supaya tidak terlalu panjang saat kita memakai widgetnya.

Pada tutorial/medium sebelumnya, Kita memasang Nama, Tempat/tanggal lahir, Jenis kelamin, dan alamat. Pada bagian alamat, kita meletakkannya khusus di dalam card.

Jadi kita akan membuat widget untuk “Nama”, “Tempat/tanggal lahir”, “Jenis kelamin” yang akan kita sebut dengan “bio umum” terpisah dengan bagian “alamat”.

Buat file baru dengan nama biodata.dart. Kemudia isi dengan syntax seperti ini:

import 'package:flutter/material.dart';class Biodata extends StatelessWidget {
String image, name, ttl, gender;
Map alamat;
Biodata(this.image, {this.name, this.ttl, this.gender,this.alamat});
@override
Widget build(BuildContext context) {
return Column(

);
}
}

Setelah itu kita buat file widget_biodata.dart untuk bagian “custom-widget” kita butuhkan .

Untuk mengingatkan seperti apa syntax waktu itu , syntaxnya seperti ini:

.............
//bio umum
Container(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.start,
children: <Widget>[
CircleAvatar(
radius: 45,
backgroundImage: ExactAssetImage('assets/srg.png', scale: 2),
),
Column(
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Container(
margin: EdgeInsets.only(right: 30, top: 10),
child: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: "Nama : ",
style:
TextStyle(fontStyle: FontStyle.italic)),
TextSpan(
text: text,
style:
TextStyle(fontWeight: FontWeight.bold)),
],
style:
TextStyle(fontSize: 14, color: Colors.black)),
)
),
Container(
margin: EdgeInsets.only(right: 30),
child: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: "Tempat/Tanggal Lahir : \n",
style:
TextStyle(fontStyle: FontStyle.italic)),
TextSpan(
text: "${tl}/${ttl}",
style:
TextStyle(fontWeight: FontWeight.bold)),
],
style:
TextStyle(fontSize: 14, color: Colors.black)),
)
),
Container(
margin: EdgeInsets.only(right: 30),
child: RichText(
text: TextSpan(
children: <TextSpan>[
TextSpan(
text: "Jenis Kelamin : ",
style:
TextStyle(fontStyle: FontStyle.italic)),
TextSpan(
text: gender,
style:
TextStyle(fontWeight: FontWeight.bold)),
],
style:
TextStyle(fontSize: 14, color: Colors.black)),
)
),
],
),
]),
),
//Alamat
Container(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Card(
child: Container(
padding:
EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.5),
height: 100,
width: MediaQuery.of(context).size.width,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RichText(
text: TextSpan(
style:
TextStyle(fontSize: 14, color: Colors.black),
children: <TextSpan>[
TextSpan(
text: "Alamat : ",
style:
TextStyle(fontStyle: FontStyle.italic)),
TextSpan(
text: alamat["alamat"],
style: TextStyle(
fontStyle: FontStyle.italic,
decoration: TextDecoration.underline)),
]),
),
Container(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 14, color: Colors.black),
children: <TextSpan>[
TextSpan(
text: "RT/RW : ",
style: TextStyle(
fontStyle: FontStyle.italic)),
TextSpan(
text: alamat["rt/rw"],
style: TextStyle(
fontStyle: FontStyle.italic,
decoration:
TextDecoration.underline)),
]),
),
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 14, color: Colors.black),
children: <TextSpan>[
TextSpan(
text: "keluran/Desa : ",
style: TextStyle(
fontStyle: FontStyle.italic)),
TextSpan(
text: alamat["kel/Desa"],
style: TextStyle(
fontStyle: FontStyle.italic,
decoration: TextDecoration.underline)),
]),
),
RichText(
text: TextSpan(
style: TextStyle(
fontSize: 14, color: Colors.black),
children: <TextSpan>[
TextSpan(
text: "kecamatan : ",
style: TextStyle(
fontStyle: FontStyle.italic)),
TextSpan(
text: alamat["kec"],
style: TextStyle(
fontStyle: FontStyle.italic,
decoration:TextDecoration.underline)),
]),
)
],
),
)
],
)),
),
)
.....................

Karena kita akan membuat syntax ini menjadi lebih pendek, kita akan membuat method untuk mengembalikan widget — widget yang terlalu sering dipanggil dengan sifat yang sama.

Pada column di kedua bagian(bio umum dan alamat) kita membuat-nya dengan sifat yang sama.

Jadi kita akan membuat menjadi method yang mengembalikan column sesuai dengan sifat yang kita butuhkan. Kita akan membuat “custom-widget” pertama.

Pergi ke widget_biodata.dart dan ketik syntax ini:

Column text_group({List<Widget> children}) {
return Column(
mainAxisAlignment: MainAxisAlignment.start,
mainAxisSize: MainAxisSize.max,
crossAxisAlignment: CrossAxisAlignment.start,
children: children,
);
}

Error? Seperti biasa. Arahkan kursor ke text bergais merah dan tekan CTRL + .(titik) . Pilih “../material.dart” .

PENJELASAN

Pada syntax ini akhirnya kita mengcustom widget. Dengan membuat method bernama text_group dan berparameter List<Widget> childern, kita bisa memanggil column dengan sifat yang sama hanya dengan menuliskan text_group ke kelas Biodata . Karena menggunakan kurung kurawa, kita menuliskannya seperti ini:(Untuk saat ini kalian tidak perlu menulis apa — apa di biodata.dart . Ini hanya contoh penggunaanya dengan mengimplementasikannya di listView.dart.)

Next, setiap bagian di dalam Column tersebut ada RichText widget dan syntaxnya juga hampis sama di 2 bagian. Jadi kita akan membuat hal yang sama. Tapi bagaimana jika widget tersebut memiliki beberapa perbedaan walau sedikit. Disini kita Memanfaatkan parameter kurung kurawa. Tulis syntax ini di widget_biodata.dart:

Widget text_widget(String text1, String text2, {double top: 0.0, String task}) {
TextStyle defaults;
if (task == "inCard") {
defaults = TextStyle(
fontStyle: FontStyle.italic, decoration: TextDecoration.underline);
} else {
defaults = TextStyle(fontWeight: FontWeight.bold);
}
return Container(
margin: EdgeInsets.only(right: 30, top: top),
child: RichText(
text: TextSpan(
style: TextStyle(fontSize: 14, color: Colors.black),
children: <TextSpan>[
TextSpan(
text: text1, style: TextStyle(fontStyle: FontStyle.italic)),
TextSpan(text: text2, style: defaults),
]),
));
}

Seperti yang dijelaskan di atas .Dengan memanfaatkan kurung kurawa, kita bisa kondisi yang berbeda sesuai yang dibutuhkan. Contohnya menggunakan if…else untuk membedakan kondisi apakah kita menggunakannya untuk bio umum, atau di alamat.

Sekarang kita buat method untuk mengembalikan widget container, yang membungkus bio umum, dan alamat. Karena widget yang membungkus kedua bagian itu memiliki banyak perbedaan, kita akan membuat 2 method.

Syntax ini untuk bio umum:

Container biodata(String image,{List<Widget> children}) {
return Container(
height: 100,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
CircleAvatar(
radius: 45,
backgroundImage: ExactAssetImage(image, scale: 2),
),
text_group(children: children)
],
),
);
}

Dan syntax ini untuk alamat:

Container card_alamat(BuildContext context, {List<Widget> children}) {
return Container(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child: Card(
child: Container(
padding: EdgeInsets.symmetric(horizontal: 8.0, vertical: 3.5),
height: 100,
width: MediaQuery.of(context).size.width,
child: text_group(children: children)),
),
);
}

Di kedua widget kita bisa langsung menempatkan method text_group. Ketika parameter children di kedua method tersebut diisikan, otomatis widget-widget dari parameter children akan dimasukkan di text_group.

Sekarang ketikkan syntax ini di biodata.dart .

import 'package:flutter/material.dart';
import 'widget_biodata.dart';
class Biodata extends StatelessWidget {
String image, name, ttl, gender;
Map alamat;
Biodata(this.image,{ this.name, this.ttl, this.gender, this.alamat});
@override
Widget build(BuildContext context) {
return Column(
children: <Widget>[
biodata(
this.image,
children: <Widget>[
text_widget("Nama : ", name, top: 10),
text_widget("Tempat/Tanggal Lahir : \n", ttl),
text_widget("Jenis Kelamin : ", gender),
]),
card_alamat(
context,
children: <Widget>[
text_widget("Alamat : ", alamat[alamat.keys.elementAt(0)],
task: "inCard"),
Container(
padding: EdgeInsets.symmetric(horizontal: 8.0),
child:
text_group(children: <Widget>[
text_widget("RT/RW : ", alamat[alamat.keys.elementAt(1)],
task: "inCard"),
text_widget("kelurahan/Desa : ", alamat[alamat.keys.elementAt(2)],
task: "inCard"),
text_widget("Kecamatan : ", alamat[alamat.keys.elementAt(3)],
task: "inCard"),
]))
],
)
],
);
}
}

Dan terakhir panggil kelas ini sama persis seperti dengan memanggil kelas widget pada bagian ListView.builder di tutorial sebelummnya. Seperti ini(ketikkan seperti ini dikelas):

Jadi kesimpulan dari tutorial kali ini, kalian bisa membuat project kalian lebih rapih dengan membuat kelas dan method di file yang berbeda. Dan memanggil kelas dan method tersebut sesuai keperluan. Menggunakan parameter di kelas dan method dapat membantu kalian menyesuaikan menggunaan kelas dan method tersebut.

Terimakasih karena mengikuti tutorial kali ini. Kurang lebihnya mohon maaf . Salam pamit.

--

--