Write a simple BMI Calculator with Flutter (Null Safety)

Last updated on July 11, 2021 A Goodman Loading... Post a comment

In this article, we’ll build a simple BMI (body mass index) calculator with Flutter from scratch.

This tutorial aims at people who are new to Flutter, so I’ll make it as simple as possible with the latest Flutter updates and features. We won’t learn old things or complicated things.

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

Prerequisites

To 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 haven’t set up Flutter yet, check this guide (Windows) or this guide (Mac).

Project Overview

Here’s 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 user’s 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 app’s 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:

Let’s Write The Logic Code

Our app now looks pretty good but it does nothing. Let’s 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

Here’s 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 you’d like to explore more about Flutter, take a look at the following articles:

You can also check out our Flutter topic page or Dart topic page for the latest tutorials and examples.

Subscribe
Notify of
guest
0 Comments
Inline Feedbacks
View all comments

Related Articles