ListTile adalah widget yang disediakan oleh Flutter. Kita coba implementasikan ListTile pada aplikasi Expense Tracker dari modul sebelumnya. Kita juga akan tambahkan fungsi delete transaksi.

ListTile dapat digunakan pada expense_list.dart, dimana list dari expense ditampilkan. Karena kita akan menggunakan widget CircleAvatar untuk menampilkan amount expense, akan kurang cocok dengan angka expense yang besar. Oleh karena itu kita akan gunakan angka kecil, seolah menggunakan hitungan dolar.
ListTile memiliki property
- leading, dapat digunakan untuk menampilkan amount expense.
- title, dapat digunakan untuk menampilkan judul expense.
- subtitle, dapat digunakan untuk menampilkan tanggal expense.
- trailing, dapat digunakan untuk menampilkan button, pada project ini untuk delete expense.
Untuk button delete, kita gunakan widget IconButton.
return Card(
margin: EdgeInsets.symmetric(vertical: 7, horizontal: 4),
elevation: 2,
child: ListTile(
leading: CircleAvatar(
radius: 50,
child: FittedBox(
child: Text(
'\$${_trans[idx].amount}',
),
),
),
title: Text(_trans[idx].title),
subtitle:
Text(DateFormat.yMMMd().format(_trans[idx].txdate)),
trailing: IconButton(
icon: Icon(Icons.delete),
color: Theme.of(context).errorColor,
onPressed: () => _delExp(_trans[idx].id),
),
),
);
Berikut isi lengkap file expense_list.dart, selain perubahan seperti pada code diatas, kita juga perlu menambahkan function handler _delExp dan mengubah constructor ExpenseList dengan menambahkan paramater this._delExp.
//expense_list.dart
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import '../models/trans.dart';
class ExpenseList extends StatelessWidget {
final List<Trans> _trans;
final Function _delExp;
ExpenseList(this._trans, this._delExp);
@override
Widget build(BuildContext context) {
return Container(
height: 300,
child: _trans.isEmpty
? Column(
children: <Widget>[
Text(
'No Expense...',
style: TextStyle(fontWeight: FontWeight.bold),
),
Container(
height: 200,
child: Image.asset(
'assets/img/empty-icon.png',
fit: BoxFit.cover,
),
),
],
)
: ListView.builder(
itemCount: _trans.length,
itemBuilder: (ctx, idx) {
return Card(
margin: EdgeInsets.symmetric(vertical: 7, horizontal: 4),
elevation: 2,
child: ListTile(
leading: CircleAvatar(
radius: 50,
child: FittedBox(
child: Text(
'\$${_trans[idx].amount}',
),
),
),
title: Text(_trans[idx].title),
subtitle:
Text(DateFormat.yMMMd().format(_trans[idx].txdate)),
trailing: IconButton(
icon: Icon(Icons.delete),
color: Theme.of(context).errorColor,
onPressed: () => _delExp(_trans[idx].id),
),
),
);
},
),
);
}
}
Kita akan menambahkan fungsi delete yang disimpan di main.dart. Fungsi yang digunakan adalah removeWhere dengan id sebagai key.
void _delExpense(String expId) {
setState(() {
_trans.removeWhere((element) {
return element.id == expId;
});
});
}
// file main.dart
import 'package:flutter/material.dart';
import './models/trans.dart';
import './widgets/expense_list.dart';
import './widgets/form_expense.dart';
import './widgets/chart.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Expense Tracker',
theme: ThemeData(
primaryColor: Colors.red,
accentColor: Colors.red[400],
textTheme: TextTheme(
bodyText2: TextStyle(
color: Colors.red,
fontFamily: 'Quicksand',
),
),
fontFamily: 'OpenSans'),
home: MyHomePage(),
);
}
}
class MyHomePage extends StatefulWidget {
@override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final List<Trans> _trans = [];
List<Trans> get _rcntTrx {
return _trans.where((element) {
return element.txdate.isAfter(DateTime.now().subtract(Duration(days: 7)));
}).toList();
}
void _addNewExpense(String newTitle, double newAmount, DateTime newDate) {
final newExpense = Trans(
id: DateTime.now().toString(),
title: newTitle,
amount: newAmount,
txdate: newDate);
setState(() {
_trans.add(newExpense);
});
}
void _showFormExpense(BuildContext ctx) {
showModalBottomSheet(
context: ctx,
builder: (_) {
return FormExpense(_addNewExpense);
},
);
}
void _delExpense(String expId) {
setState(() {
_trans.removeWhere((element) {
return element.id == expId;
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('Expense Tracker'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _showFormExpense(context),
)
],
),
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Chart(_rcntTrx),
ExpenseList(_trans, _delExpense),
]),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _showFormExpense(context),
),
);
}
}