Flutter Showcase: Basic Calculator App (Part 1)
Simple calculator app with Flutter
Setelah kita telah mempelajari dasar-dasar pembuatan layout di Flutter pada series berikut.
Sekarang saatnya kita buat aplikasi pertama kita di Flutter yaitu, aplikasi Basic Calculator dimana, aplikasi ini berfungsi untuk melakukan perhitungan sederhana pada kalkulator seperti penjumlahan, pengurangan, perkalian, dan pembagian. Berikut gambaran hasil akhir dari aplikasi yang akan kita buat.
Stateless and Stateful Widget
Sebelum kita membuat aplikasinya ada hal yang ini saya sampaikan terlebih dahulu mengenai StatelessWidget
dan StatefulWidget
dimana, istilah ini harus kita pahami terlebih dahulu sebelum kita membuat aplikasi goal kita. Berdasarkan dokumentasinya disebutkan seperti berikut.
StatelessWidget is a widget that does not require mutable state. StatefulWidget is a widget that has mutable state.
Jadi, kesimpulannya kita ambil secara sederhana saja bahwa StatelessWidget
dipakai ketika kita membuat layout yang mana layout-nya itu bersifat statik dan tidak bergantung dengan perubahan apapun. Sementara, StatefulWidget
dipakai ketika kita membuat layout yang mana layout-nya bersifat dinamis dan bergantung dengan perubahan apapun.
Step 1: Started Create Project
Pada artikel ini saya menggunakan Android Studio sebagai IDE-nya jadi, harap disesuaikan sesuai dengan IDE favoritnya masing-masing. Buka aplikasi Android Studio dan pilih Start a new Flutter project.
Lalu, pilih Flutter Application.
Selanjutnya, isi nama projeknya dan keterangan lainnya seperti berikut. (Harap disesuaikan dengan konfigurasi di perangkatnya masing-masing).
Selanjutnya, isi nama package-nya sesuai dengan yang kita inginkan dan konfigurasi platform channel language-nya.
Selanjutnya, pilih Finish dan tunggu sampai projek selesai dibuat.
Step 2: Setup Configuration Dependency
Pada aplikasi, kita ada menggunakan dependency auto_size_text
dengan versi 0.3.0 atau yang lebih terbaru. Silakan buka file pubspec.yaml dan pada bagian dependencies
-nya tambahkan dependency auto_size_text
seperti berikut.
dependencies:
flutter:
sdk: flutter
# The following adds the Cupertino Icons font to your application.
# Use with the CupertinoIcons class for iOS style icons.
cupertino_icons: ^0.1.2
# Resizes text to fit perfectly within its bounds.
auto_size_text: ^0.3.0
Selanjutnya, pilih Package Get untuk mengunduh dependency-nya.
Step 3: Create Layout
Sebelum kita mulai membuat layout-nya lebih baik kita analisis terlebih dahulu layout berikut.
Awalnya kita bagi 2 penampung layout-nya yaitu pada bagian atas dan bagian bawah dengan ukuran sama besar.
Maka, awalnya kita buat layout awalnya seperti berikut.
void main() => runApp(MainApp());
class MainApp extends StatefulWidget {
@override
CalculatorAppState createState() => CalculatorAppState();
}
class CalculatorAppState extends State<MainApp> {
final double _padding = 16.0;
final Color _primarySwatchColor = Colors.orange;
final Color _titleAppBarColor = Colors.white;
@override
Widget build(BuildContext context) {
return MaterialApp(
theme: ThemeData(primarySwatch: _primarySwatchColor),
home: Scaffold(
appBar: AppBar(
title: Text(
"Basic Calculator",
style: TextStyle(color: _titleAppBarColor),
),
),
body: Column(
children: <Widget>[
Expanded(
key: Key("expanded_bagian_atas"),
flex: 1,
child: Container(
key: Key("expanded_container_bagian_atas"),
width: double.infinity,
height: double.infinity,
),
),
Expanded(
key: Key("expanded_bagian_bawah"),
flex: 1,
child: Container(
key: Key("expanded_container_bagian_bawah"),
width: double.infinity,
height: double.infinity,
),
)
],
),
),
);
}
}
Sekarang kita lihat hasilnya.
Selanjutnya, kita tambahkan Stack
kedalam widget expanded_container_bagian_atas
dan didalam Stack
kita tambahkan widget AutoSizeText
seperti berikut.
Expanded(
key: Key("expanded_bagian_atas"),
flex: 1,
child: Container(
key: Key("expanded_container_bagian_atas"),
width: double.infinity,
height: double.infinity,
padding: EdgeInsets.all(_padding),
child: Stack(
alignment: Alignment.bottomRight,
children: <Widget>[
AutoSizeText(
"0",
style: Theme.of(context).textTheme.display2,
maxLines: 1,
),
],
),
),
)
Dan sekarang lihat outputnya.
Sekarang kita fokus ke widget expanded_container_bagian_bawah
. Konsepnya sama seperti cara kita sebelumnya yang membuat layout utama menjadi 2 bagian yang sama besar. Jadi, analisisnya adalah kita ganti terlebih dahulu widget Container
dengan key expanded_container_bagian_bawah
menjadi Column
seperti berikut.
Lalu, kita tambahkan widget Expanded
sebanyak 5 kedalam expanded_column_bagian_bawah
dan disetiap Expanded
kita tambahkan Row
seperti berikut.
Dan berikut untuk Expanded
pertama dan Row
didalamnya.
child: Column(
key: Key("expanded_column_bagian_bawah"),
children: <Widget>[
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 2,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"C",
style: TextStyle(
color: _primarySwatchColor,
fontSize: _buttonFontSize),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Icon(
Icons.backspace,
color: _buttonColorGrey,
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"/",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
)
],
),
)
],
),
Pada kode diatas kita ada penambahan Color
sebagai objek. Jadi, silakan kita tambahkan seperti berikut.
final double _padding = 16.0;
final double _buttonFontSize = 24.0;
final Color _primarySwatchColor = Colors.orange;
final Color _titleAppBarColor = Colors.white;
final Color _buttonColorWhite = Colors.white;
final Color _buttonHighlightColor = Colors.grey[800];
final Color _buttonColorGrey = Colors.grey[500];
Sekarang coba kita lihat hasilnya.
Berikutnya coba kita tambahkan Expanded
kedua didalam expanded_column_bagian_bawah
.
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"7",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"8",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"9",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"x",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
],
),
),
Sekarang coba jalankan lagi maka, outputnya seperti berikut.
Untuk Expanded
ketiga sampai kelima silakan tambahkan sendiri ya dan lakukan hal yang sama seperti Expanded
sebelumnya. Berikut source code lengkapnya untuk expanded_column_bagian_bawah
.
Expanded(
key: Key("expanded_bagian_bawah"),
flex: 1,
child: Column(
key: Key("expanded_column_bagian_bawah"),
children: <Widget>[
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 2,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"C",
style: TextStyle(
color: _primarySwatchColor,
fontSize: _buttonFontSize),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Icon(
Icons.backspace,
color: _buttonColorGrey,
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"/",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
)
],
),
),
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"7",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"8",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"9",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"x",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
],
),
),
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"4",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"5",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"6",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"-",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
],
),
),
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"1",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"2",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"1",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"+",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
],
),
),
Expanded(
flex: 1,
child: Row(
crossAxisAlignment: CrossAxisAlignment.stretch,
children: <Widget>[
Expanded(
flex: 3,
child: RaisedButton(
color: _buttonColorWhite,
highlightColor: _buttonHighlightColor,
child: Text(
"0",
style: TextStyle(
color: _buttonColorGrey,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
Expanded(
flex: 1,
child: RaisedButton(
color: _primarySwatchColor,
highlightColor: _buttonHighlightColor,
child: Text(
"=",
style: TextStyle(
color: _textColorWhite,
fontSize: _buttonFontSize,
),
),
onPressed: () {
// TODO: do something in here
},
),
),
],
),
),
],
),
)
Pada kode lengkap diatas, bisa kita lihat ada satu objek _textColorWhite
dimana, ini nilainya adalah seperti berikut.
final Color _textColorWhite = Colors.white;
Sekarang coba jalankan lagi maka, outputnya seperti berikut.
Conclusion
Saya rasa untuk bagian pertama pada artikel ini kita fokus sampai ke pembuatan layout-nya saja nanti di bagian keduanya kita akan mulai bahas bagaimana pembuatan logic program-nya. Berikut untuk link bagian keduanya.