Flutter Showcase: Basic Calculator App (Part 1)

Simple calculator app with Flutter

Yudi Setiawan
Nusanet Developers
8 min readDec 27, 2018

--

Basic Calculator App

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.

Goal

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.

Mulai membuat Flutter projek

Lalu, pilih Flutter Application.

Pilih Flutter Application

Selanjutnya, isi nama projeknya dan keterangan lainnya seperti berikut. (Harap disesuaikan dengan konfigurasi di perangkatnya masing-masing).

Isi nama projek dan keterangan lainnya

Selanjutnya, isi nama package-nya sesuai dengan yang kita inginkan dan konfigurasi platform channel language-nya.

Isi nama package dan platform channel language

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.

Update dependency

Step 3: Create Layout

Sebelum kita mulai membuat layout-nya lebih baik kita analisis terlebih dahulu layout berikut.

Analisis Layout

Awalnya kita bagi 2 penampung layout-nya yaitu pada bagian atas dan bagian bawah dengan ukuran sama besar.

Layout utamanya kita bagi menjadi 2 bagian yang 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.

Buat layout utama dibagi menjadi 2 bagian yang sama besar

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.

Tambahkan widget AutoSizeText kedalam expanded_container_bagian_atas

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.

Ganti widget expanded_container_bagian_bawah menjadi Column

Lalu, kita tambahkan widget Expanded sebanyak 5 kedalam expanded_column_bagian_bawah dan disetiap Expanded kita tambahkan Row seperti berikut.

Analisis expanded_column_bagian_bawah

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.

Penambahan expanded pertama didalam expanded_column_bagian_bawah

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.

Penambahan expanded kedua didalam expanded_column_bagian_bawah

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.

Hasil akhir pembuatan layout

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.

--

--