In this article, well build a simple BMI (body mass index) calculator with Flutter from scratch.
This tutorial aims at people who are new to Flutter, so Ill make it as simple as possible with the latest Flutter updates and features. We wont learn old things or complicated things.Advertisements
What you need to know first is the BMI formula:
BMI = weight (kg) / [height (m)]2
If you want to dig deeper about BMI, take a look at this article on Wikipedia.
Note: This article was recently updated to migrate to null safety and work well with Flutter 2.2.3 or newer
Table of Contents
Prerequisites
AdvertisementsTo follow along with this tutorial, you need the following:
- Flutter SDK installed on your computer
- iOS Simulator or Android emulator installed
- Flutter version 2.2.3 or newer
- Know how to create a new Flutter project
If you havent set up Flutter yet, check this guide (Windows) or this guide (Mac).
Project Overview
Heres how our app works at the end of this tutorial:
The BMI will be calculated as soon as the user presses the button. In addition to the BMI result shows up on the screen there will be a simple message about the users body condition.
Starting a new Flutter project
1. In your terminal window, navigate to the place you would like your new Flutter application to be located an run the following command:
flutter create bmi_example
2. Start an iOS simulator or an Android emulator:
3. Navigate into the new project directory:
cd bmi_example
Then boost it up:
flutter run
4. Remove everything in your lib/main.dart and add this starter code:
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
@override
Widget build(BuildContext context) {
return Scaffold(body: Center());
}
}
Hot restart the app by pressing Shift + R and you will see this:
Building the UI
In this step, we will build the apps UI and register the controllers for the text fields.
Modify the _HomePageState class like this:
class _HomePageState extends State<HomePage> {
// the controller for the text field associated with "height"
final _heightController = TextEditingController();
// the controller for the text field associated with "weight"
final _weightController = TextEditingController();
double? _bmi;
// the message at the beginning
String _message = 'Please enter your height an weight';
// This function is triggered when the user pressess the "Calculate" button
void _calculate() {}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.deepOrange,
body: Center(
child: Container(
width: 320,
child: Card(
color: Colors.white,
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
keyboardType:
TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(labelText: 'Height (m)'),
controller: _heightController,
),
TextField(
keyboardType:
TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: 'Weight (kg)',
),
controller: _weightController,
),
ElevatedButton(
onPressed: _calculate,
child: Text('Calculate'),
),
SizedBox(
height: 30,
),
Container(
child: Text(
_bmi == null ? 'No Result' : _bmi!.toStringAsFixed(2),
style: TextStyle(fontSize: 50),
textAlign: TextAlign.center,
),
),
SizedBox(
height: 20,
),
Container(
child: Text(
_message,
textAlign: TextAlign.center,
),
)
],
),
),
),
),
));
}
}
Reload the app and you will see this:
Lets Write The Logic Code
Our app now looks pretty good but it does nothing. Lets add the necessary logic to the _calculate function:
void _calculate() {
final double? height = double.tryParse(_heightController.value.text);
final double? weight = double.tryParse(_weightController.value.text);
// Check if the inputs are valid
if (height == null || height <= 0 || weight == null || weight <= 0) {
setState(() {
_message = "Your height and weigh must be positive numbers";
});
return;
}
setState(() {
_bmi = weight / (height * height);
if (_bmi! < 18.5) {
_message = "You are underweight";
} else if (_bmi! < 25) {
_message = 'You body is fine';
} else if (_bmi! < 30) {
_message = 'You are overweight';
} else {
_message = 'You are obese';
}
});
}
Now hot restart the app and check it out:
The Final Code
Heres the complete code:
// main.dart
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
title: 'Kindacode.com',
home: HomePage(),
);
}
}
class HomePage extends StatefulWidget {
@override
_HomePageState createState() => _HomePageState();
}
class _HomePageState extends State<HomePage> {
// the controller for the text field associated with "height"
final _heightController = TextEditingController();
// the controller for the text field associated with "weight"
final _weightController = TextEditingController();
// The BMI
double? _bmi;
// the message at the beginning
String _message = 'Please enter your height an weight';
void _calculate() {
final double? height = double.tryParse(_heightController.value.text);
final double? weight = double.tryParse(_weightController.value.text);
// Check if the inputs are valid
if (height == null || height <= 0 || weight == null || weight <= 0) {
setState(() {
_message = "Your height and weigh must be positive numbers";
});
return;
}
setState(() {
_bmi = weight / (height * height);
if (_bmi! < 18.5) {
_message = "You are underweight";
} else if (_bmi! < 25) {
_message = 'You body is fine';
} else if (_bmi! < 30) {
_message = 'You are overweight';
} else {
_message = 'You are obese';
}
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
backgroundColor: Colors.deepOrange,
body: Center(
child: Container(
width: 320,
child: Card(
color: Colors.white,
elevation: 10,
child: Padding(
padding: const EdgeInsets.all(20),
child: Column(
mainAxisSize: MainAxisSize.min,
children: [
TextField(
keyboardType:
TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(labelText: 'Height (m)'),
controller: _heightController,
),
TextField(
keyboardType:
TextInputType.numberWithOptions(decimal: true),
decoration: InputDecoration(
labelText: 'Weight (kg)',
),
controller: _weightController,
),
ElevatedButton(
onPressed: _calculate,
child: Text('Calculate'),
),
SizedBox(
height: 30,
),
Container(
child: Text(
_bmi == null ? 'No Result' : _bmi!.toStringAsFixed(2),
style: TextStyle(fontSize: 50),
textAlign: TextAlign.center,
),
),
SizedBox(
height: 20,
),
Container(
child: Text(
_message,
textAlign: TextAlign.center,
),
)
],
),
),
),
),
));
}
}
Conclusion
Congratulation. You have made a Flutter application. While this is only a simple application, it is a great starting point for working through more complex and difficult projects. If youd like to explore more about Flutter, take a look at the following articles:
- Make a Scroll Back To Top button
- Working with TextButton in Flutter
- Working with ElevatedButton in Flutter
- How to create Circle Charts (Pie Charts) in Flutter
- Using GetX (Get) for Navigation and Routing in Flutter
- Using GetX (Get) for State Management in Flutter
- Flutter and Firestore Database: CRUD example (null safety)
You can also check out our Flutter topic page or Dart topic page for the latest tutorials and examples.