Jika Anda pernah develop web, tentu istilah MediaQuery tidak asing lagi. Dengan menggunakan MediaQuery, kita bisa mendapatkan informasi ukuran suatu object.
Mari kita coba implementasikan untuk aplikasi expense tracker. Buka file main.dart, lalu tambahkan code berikut.
final _screenSize = MediaQuery.of(context).size.height -
_appBar.preferredSize.height -
MediaQuery.of(context).padding.top;
- MediaQuery.of(context).padding.top adalah untuk mendapatkan tinggi system status bar diatas (yang berisi info jaringan, jam, batterai dan lainnya)
- MediaQuery.of(context).size.height adalah informasi tinggi total dari device.
- _appBar.preferredSize.height, adalah tiggi dari appBar. Namun untuk mendapatkan tinggi appBar, kita harus membuat variable _appBar yang berisi widget appBar.
final _appBar = AppBar(
title: Text('Expense Tracker'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _showFormExpense(context),
)
],
);
Perhitungan diatas akan digunakan saat menampilkan widget Chart dan Expense List
return Scaffold(
appBar: _appBar,
...
...
...
// variable _screenSize digunakan disini
Container(height: _screenSize * 0.3, child: Chart(_rcntTrx)),
Container(
height: _screenSize * 0.7,
child: ExpenseList(_trans, _delExpense)),
]),
),
Berikut isi akhir dari 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) {
final _appBar = AppBar(
title: Text('Expense Tracker'),
actions: <Widget>[
IconButton(
icon: Icon(Icons.add),
onPressed: () => _showFormExpense(context),
)
],
);
final _screenSize = MediaQuery.of(context).size.height -
_appBar.preferredSize.height -
MediaQuery.of(context).padding.top;
return Scaffold(
appBar: _appBar,
body: SingleChildScrollView(
child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Container(height: _screenSize * 0.3, child: Chart(_rcntTrx)),
Container(
height: _screenSize * 0.7,
child: ExpenseList(_trans, _delExpense)),
]),
),
floatingActionButtonLocation: FloatingActionButtonLocation.centerFloat,
floatingActionButton: FloatingActionButton(
child: Icon(Icons.add),
onPressed: () => _showFormExpense(context),
),
);
}
}
Karena ukuran widget sudah kita hitung pada main.dart, maka ukuran hardcode pada expense_list.dart dapat kita buang.
Widget build(BuildContext context) {
//bagian container bisa kita buang
return Container(
height: 300,
child: _trans.isEmpty
? Column(
children: <Widget>[
Berikut hasil akhir 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 _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),
),
),
);
},
);
}
}