Menu
CoddyTech

Tip Calculator: People

Part of the Making It Interactive section of Coddy's Flutter journey. Lesson 32 of 34.

A bill is often shared. Add a row with the number of people and two icon buttons, minus and plus, like the counter you built in A Counter Up and Down.

There is always at least one person paying, so the minus button greys out at 1. An IconButton greys out the same way as other buttons, with onPressed: null. When the function is short, you can write it right inside the ? ::

onPressed: _people > 1
    ? () {
        setState(() {
          _people--;
        });
      }
    : null,

A SizedBox(width: 16) in the row keeps the buttons a little away from the text.

challenge icon

Challenge

Easy
  • Keep the number of people in int _people = 1;
  • Under the tip amount, add a Row with People: 1, an IconButton with Icons.remove and one with Icons.add.
  • Plus adds a person. Minus takes one away, and is greyed out at 1.

Try it yourself

import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      debugShowCheckedModeBanner: false,
      home: const HomePage(),
    );
  }
}

class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<HomePage> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> {
  double _bill = 0;
  double _tipPercent = 10;

  @override
  Widget build(BuildContext context) {
    final double tip = _bill * _tipPercent / 100;
    return Scaffold(
      appBar: AppBar(title: const Text('Tip Calculator')),
      body: Padding(
        padding: const EdgeInsets.all(24),
        child: Column(
          crossAxisAlignment: CrossAxisAlignment.start,
          children: [
            TextField(
              keyboardType: const TextInputType.numberWithOptions(decimal: true),
              decoration: const InputDecoration(
                labelText: 'Bill',
                border: OutlineInputBorder(),
              ),
              onChanged: (String value) {
                setState(() {
                  _bill = double.tryParse(value) ?? 0;
                });
              },
            ),
            const SizedBox(height: 8),
            Text('Bill: ${_bill.toStringAsFixed(2)}'),
            const SizedBox(height: 24),
            Text('Tip: ${_tipPercent.round()}%', style: const TextStyle(fontSize: 20)),
            Slider(
              value: _tipPercent,
              min: 0,
              max: 30,
              divisions: 6,
              onChanged: (double value) {
                setState(() {
                  _tipPercent = value;
                });
              },
            ),
            Text('Tip amount: ${tip.toStringAsFixed(2)}'),
          ],
        ),
      ),
    );
  }
}
quiz iconTest yourself

This lesson includes a short quiz. Start the lesson to answer it and track your progress.

All lessons in Making It Interactive

Practice on your own: Online Flutter compiler