Menu
CoddyTech

Calculadora de propinas: Personas

Parte de la sección Cómo hacerla interactiva del Journey de Flutter de Coddy. Lección 32 de 34.

Una cuenta suele compartirse. Añade una fila con el número de personas y dos botones con iconos, uno de menos y otro de más, como el contador que creaste en A Counter Up and Down.

Siempre hay al menos una persona que paga, así que el botón de menos se atenúa cuando hay 1. Un IconButton se atenúa igual que los demás botones, con onPressed: null. Cuando la función es corta, puedes escribirla directamente dentro de ? ::

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

Un SizedBox(width: 16) en la fila mantiene los botones un poco alejados del texto.

challenge icon

Desafío

Fácil
  • Mantén el número de personas en int _people = 1;
  • Debajo del importe de la propina, añade una Row con People: 1, un IconButton con Icons.remove y otro con Icons.add.
  • El signo más añade una persona. El signo menos resta una, y aparece atenuado cuando hay 1.

Pruébalo tú mismo

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 iconPonte a prueba

Esta lección incluye un breve cuestionario. Empieza la lección para responderlo y registrar tu progreso.

Todas las lecciones de Cómo hacerla interactiva

Practica por tu cuenta: Compilador de Flutter online