Aplicacions amb Flutter, Dart i Flame

Tutorial Flutter Flame Projectes   Recursos CITCEA
Exemples Dart Dades pràctiques     Inici

Programa final per a aquesta aplicació

Arribats a aquest punt, l'aplicació, vista amb l'emulador, té aquest aspecte:

Pantalla

Un cop acabat el programa, anem a posar el contingut complet dels diferents fitxers de programa. Comencem pel programa principal:

main.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
import 'package:resistled_app/screens/pant_principal.dart';
void main() {
  runApp(const MainApp());
}
class MainApp extends StatelessWidget {
  const MainApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text("Resistència per a un led"),
          backgroundColor: ColorsApp.primari,
          foregroundColor: ColorsApp.text,
        ),
        backgroundColor: ColorsApp.fons,
        body: PantPral(),
      ),
    );
  }
}

Carpeta screens

pant_principal.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/components/boto_calc.dart';
import 'package:resistled_app/components/entra_num.dart';
import 'package:resistled_app/components/req_result.dart';
import 'package:resistled_app/components/selector_tens.dart';
class PantPral extends StatefulWidget {
  const PantPral({super.key});

  @override
  State<PantPral> createState() => _PantPralState();
}

class _PantPralState extends State<PantPral> {
  double tensAlim = 3.3; // V
  double caigudaTens = 1.6; // V
  double correntNom = 10; // mA
  double resisten = -1;
  String txt = "";
  final double maxCaig = 3.3;
  final double minCaig = 0.4;
  final double maxCorr = 50.0;
  final double minCorr = 1.0;
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        SelectorTens(
          tensioAlim: tensAlim,
          canviTens: (double novaTensio) {
            setState(() {
              tensAlim = novaTensio;
              resisten = -1;
            });
          },
        ),
        Padding(
          padding: const EdgeInsets.only(left: 20, right: 20),
          child: Row(
            children: [
              Expanded(
                child: EntraNum(
                  titol: "Caiguda de tensió",
                  valor: caigudaTens.toStringAsFixed(1).replaceAll('.', ','),
                  unitats: "V",
                  incrementar: () {
                    setState(() {
                      if (caigudaTens < maxCaig) {
                        caigudaTens += 0.1;
                        resisten = -1;
                      }
                    });
                  },
                  decrementar: () {
                    setState(() {
                      if (caigudaTens > minCaig) {
                        caigudaTens -= 0.1;
                        resisten = -1;
                      }
                    });
                  },
                ),
              ),
              SizedBox(width: 20),
              Expanded(
                child: EntraNum(
                  titol: "Corrent nominal",
                  valor: correntNom.toStringAsFixed(0).replaceAll('.', ','),
                  unitats: "mA",
                  incrementar: () {
                    setState(() {
                      if (correntNom < maxCorr) {
                        correntNom++;
                        resisten = -1;
                      }
                    });
                  },
                  decrementar: () {
                    setState(() {
                      if (correntNom > minCorr) {
                        correntNom--;
                        resisten = -1;
                      }
                    });
                  },
                ),
              ),
            ],
          ),
        ),
        BotoCalc(
          calcRes: () {
            setState(() {
              resisten = (tensAlim - caigudaTens) / (correntNom / 1000);
            });
          },
        ),
        ReqResult(resistencia: resisten),
      ],
    );
  }
}

Carpeta components

selector_tens.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
import 'package:resistled_app/core/estils.dart';
class SelectorTens extends StatefulWidget {
  final double tensioAlim;
  final Function(double novaTens) canviTens;
  const SelectorTens({super.key, required this.tensioAlim, required this.canviTens});

  @override
  State<SelectorTens> createState() => _SelectorTensState();
}

class _SelectorTensState extends State<SelectorTens> {
  @override
  Widget build(BuildContext context) {
    return Row(
      children: [
        Expanded(
          child: GestureDetector(
            onTap: () {
              setState(() {
                widget.canviTens(3.3);
              });
            },
            child: Padding(
              padding: const EdgeInsets.only(top: 20, bottom: 20, left: 20, right: 10),
              child: Container(
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: widget.tensioAlim == 3.3 ? ColorsApp.compSelec : ColorsApp.component,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Text("3,3 V", style: Estils.estilTextBotons),
                ),
              ),
            ),
          ),
        ),
        Expanded(
          child: GestureDetector(
            onTap: () {
              setState(() {
                widget.canviTens(5.0);
              });
            },
            child: Padding(
              padding: const EdgeInsets.only(top: 20, bottom: 20, left: 10, right: 20),
              child: Container(
                alignment: Alignment.center,
                decoration: BoxDecoration(
                  color: widget.tensioAlim == 5.0 ? ColorsApp.compSelec : ColorsApp.component,
                  borderRadius: BorderRadius.circular(12),
                ),
                child: Padding(
                  padding: const EdgeInsets.all(20.0),
                  child: Text("5,0 V", style: Estils.estilTextBotons),
                ),
              ),
            ),
          ),
        ),
      ],
    );
  }
}

entra_num.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
import 'package:resistled_app/core/decora.dart';
import 'package:resistled_app/core/estils.dart';
class EntraNum extends StatefulWidget {
  final String titol;
  final String valor;
  final String unitats;
  final Function() incrementar;
  final Function() decrementar;
  const EntraNum({
    super.key,
    required this.titol,
    required this.valor,
    required this.unitats,
    required this.incrementar,
    required this.decrementar,
  });

  @override
  State<EntraNum> createState() => _EntraNumState();
}

class _EntraNumState extends State<EntraNum> {
  @override
  Widget build(BuildContext context) {
    return Container(
      alignment: Alignment.center,
      decoration: BoxDecoration(
        color: ColorsApp.component,
        borderRadius: BorderRadius.circular(12),
      ),
      child: Padding(
        padding: const EdgeInsets.all(20.0),
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Text(widget.titol, style: Estils.estilTextTitols),
            Text('${widget.valor} ${widget.unitats}', style: Estils.estilTextValors),
            Row(
              mainAxisAlignment: MainAxisAlignment.center,
              children: [
                Container(
                  decoration: DecoraApp.decorBotons,
                  child: IconButton(
                    onPressed: () {
                      widget.decrementar();
                    },
                    icon: Icon(Icons.remove),
                    color: ColorsApp.text,
                  ),
                ),
                SizedBox(width: 15),
                Container(
                  decoration: DecoraApp.decorBotons,
                  child: IconButton(
                    onPressed: () {
                      widget.incrementar();
                    },
                    icon: Icon(Icons.add),
                    color: ColorsApp.text,
                  ),
                ),
              ],
            ),
          ],
        ),
      ),
    );
  }
}

boto_calc.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
import 'package:resistled_app/core/estils.dart';
class BotoCalc extends StatefulWidget {
  final Function() calcRes;
  const BotoCalc({super.key, required this.calcRes});

  @override
  State<BotoCalc> createState() => _BotoCalcState();
}

class _BotoCalcState extends State<BotoCalc> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20),
      child: GestureDetector(
        onTap: () {
          setState(() {
            widget.calcRes();
          });
        },
        child: Container(
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: ColorsApp.primari,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Text("Calcula...", style: Estils.estilTextBotons),
          ),
        ),
      ),
    );
  }
}

req_result.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
import 'package:resistled_app/core/estils.dart';
class ReqResult extends StatefulWidget {
  final double resistencia;
  const ReqResult({super.key, required this.resistencia});

  @override
  State<ReqResult> createState() => _ReqResultState();
}

class _ReqResultState extends State<ReqResult> {
  @override
  Widget build(BuildContext context) {
    String txt = widget.resistencia >= 0
        ? "La resistència adequada és de: \n${widget.resistencia.toStringAsFixed(2).replaceAll('.', ',')} Ω"
        : "";
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.only(left: 20, right: 20, bottom: 40),
        child: Container(
          alignment: Alignment.center,
          decoration: BoxDecoration(
            color: ColorsApp.component,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Padding(
            padding: const EdgeInsets.all(20.0),
            child: Text(txt, style: Estils.estilTextResultat),
          ),
        ),
      ),
    );
  }
}

Carpeta core

colors.dart
import 'dart:ui';
class ColorsApp {
  static const Color fons = Color(0xFF004400);
  static const Color primari = Color(0xFF008800);
  static const Color text = Color(0xFFFFFFFF);
  static const Color component = Color(0xFF006600);
  static const Color compSelec = Color(0xFF00AA00);
}

decora.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
class DecoraApp {
  static BoxDecoration decorBotons = BoxDecoration(
    color: ColorsApp.primari,
    borderRadius: BorderRadius.circular(12),
  );
}

estils.dart
import 'package:flutter/material.dart';
import 'package:resistled_app/core/colors.dart';
class Estils {
  static const TextStyle estilTextBotons = TextStyle(
    color: ColorsApp.text,
    fontSize: 30,
    fontWeight: FontWeight.bold,
  );
  static const TextStyle estilTextTitols = TextStyle(
    color: ColorsApp.text,
    fontSize: 14,
    fontWeight: FontWeight.bold,
  );
  static const TextStyle estilTextValors = TextStyle(
    color: ColorsApp.text,
    fontSize: 18,
    fontWeight: FontWeight.bold,
  );
  static const TextStyle estilTextResultat = TextStyle(
    color: ColorsApp.text,
    fontSize: 20,
    fontWeight: FontWeight.bold,
  );
}

 

 

 

 

 

 

 

 

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.