Tip Calculator in Flutter

Photo by Sam Dan Truong on Unsplash

Hey folks, in this article you will be working on a tip calculator app from scratch. The final app will be functional both for Android and IOS. The app will be having four different options, two of which will be editable, i.e, add a total amount and add a tip percentage whereas two options won’t be editable i.e, total calculated tip and total calculated amount. Let us start with the development process.

To get started, the first thing which needs to be done is creating a default Flutter app. You can create a default Flutter app by running the Flutter pub get command. Once the app creation takes place you will be having a default counter app which on running will show you the output as shown in the image below.

Some variables need to be created which will be used for storing the values taken from the user and later display the calculated result to the user.

static const defaultBillAmount = 0.0;static const defaultTipPercentage = 15;

These variables are of type static const as the value of these won’t be changing throughout.

Some more variables need to be added for bill amount, tip percentage. Initializing the Text Editing Controller for bill amount and tip percentage, along with this. These text editing controllers will be used for keeping a track of the change in the bill amount and the tip percentage.

final _billAmountController =TextEditingController(text: defaultBillAmount.toString());final _tipPercentageController =TextEditingController(text: defaultTipPercentage.toString());double _billAmount = defaultBillAmount;int _tipPercentage = defaultTipPercentage;

Next, add two functions which will be keeping a track of the change in the value of bill amount and tip amount. If the default values of these variables are changed, these functions will update the value in form of double and int. Adding an edge case as well which will result in setting the value to 0.0 if the value cannot be parsed as a double. A set state method has been used to let the framework know about the change in the state of the app.

_onBillAmountChanged() {setState(() {_billAmount = double.tryParse(_billAmountController.text) ?? 0.0;});}_onTipAmountChanged() {setState(() {_tipPercentage = int.tryParse(_tipPercentageController.text) ?? 0;});}

Build and run to see the changes.

Text value from the controllers is being used to parse the values, the reason being, it will update the things on the go.

Next, an initState method will be there which will be running as soon as the screen is displayed/rendered. A listener is added who will be listening to the change in the value of bill amount and tip amount and will be setting the values accordingly.

@overridevoid initState() {super.initState();_billAmountController.addListener(_onBillAmountChanged);_tipPercentageController.addListener(_onTipAmountChanged);}

Build and run to see the necessary changes.

Next, creating functions to calculate the tip amount and the total amount.

_getTipAmount() => _billAmount * _tipPercentage / 100;_getTotalAmount() => _billAmount + _getTipAmount();

Now working on the appbar and the body part of the app. For the appbar, replacing the current title with a new String inside the Text widget for the title is to be done.

appBar: AppBar(title: Text(‘Tip Calculator!’),),

Build and run to see the necessary changes.

For the body part, adding padding as the top-level widget with a value of 16 from all the sides and it will be having a center widget as its child.

body: Padding(padding: const EdgeInsets.all(16.0),child: Center(),),

Build and run to see the necessary changes.

For the child of the center widget, a form will be added that will be having a column with main axis alignment set to the center.

body: Padding(padding: const EdgeInsets.all(16.0),child: Center(child: Form(child: Column(mainAxisAlignment: MainAxisAlignment.center,children: <Widget>[],),),),),

Build and run to see the necessary changes.

For the children inside the column, adding two Text form fields with the keys set to the specific names related to the usage of those text form fields. For the controller of the first text form field, we need to set it to bill amount controller, and for the controller for the second text form controller, we need to set it to tip percentage controller. These controllers will be resulting in updating and calculating the values of tip amount and total amount on the go.

TextFormField(key: Key(“billAmount”),controller: _billAmountController,),TextFormField(key: Key(“tipPercentage”),controller: _tipPercentageController,),

Build and run to see the necessary changes.

The keyboard type of the first text form field is set to input decimal values as well so setting the keyboard accordingly. For the second text form field, the basic keyboard type with numbers would be fine. Some decoration needs to be added to the text form fields to let the user know about the same. This is how the updated text form fields look like.

TextFormField(key: Key(“billAmount”),controller: _billAmountController,keyboardType: TextInputType.numberWithOptions(decimal: true),decoration: InputDecoration(hintText: ‘Enter the Bill Amount’,labelText: ‘Bill Amount’,),),TextFormField(key: Key(“tipPercentage”),controller: _tipPercentageController,keyboardType: TextInputType.number,decoration: InputDecoration(hintText: ‘Enter the Tip %’,labelText: ‘Tip %’,),),

Build and run to see the necessary changes.

Adding two text widgets below the text form field which will be displaying the tip amount and the total amount.

Text(‘Tip Amount: ${_getTipAmount()}’,key: Key(‘tipAmount’),),Text(‘Total Amount: ${_getTotalAmount()}’,key: Key(‘totalAmount’),),

Last but not the least, to avoid leaking any data so disposing of the text editing controller from the memory as soon as the widget is cleared from the memory is to be done.

@overridevoid dispose() {_billAmountController.dispose();_tipPercentageController.dispose();super.dispose();}

Let us hot reload and see if the implemented functionalities work as expected. This is how the app looks after a hot reload.

Add styles to the text widget and the raised button.

For reference:

Source code for the project can be downloaded here.

In this article, you worked on developing a tip calculator app. This app is only a starting. There is so much more which you can build with Flutter.

You can check out this article by Ashish Singh which mentions 10 awesome projects which you can work on with Flutter.

If you have any questions or comments, please join the forum discussion below.

Learning skills apart from Knowledge.