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 principal       Pantalla de resultats

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:selector_color/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: PantPral()
    );
  }
}

Carpeta screens

pant_principal.dart
import 'package:flutter/material.dart';
import 'package:selector_color/components/boto_seguir.dart';
import 'package:selector_color/components/cursor.dart';
import 'package:selector_color/components/mostra_color.dart';
import 'package:selector_color/core/colors.dart';
class PantPral extends StatefulWidget {
  const PantPral({super.key});

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

class _PantPralState extends State<PantPral> {
  List<double> valors = [127, 127, 127];
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text("Tria un color"),
        backgroundColor: ColorsApp.primari,
        foregroundColor: ColorsApp.text,
      ),
      backgroundColor: ColorsApp.fons,
      body: Column(
        children: [
          Cursor(
            titol: "Vermell:",
            valor: valors[0],
            colCurs: ColorsApp.colCursors[0],
            siCanvia: (nouValor) {
              setState(() {
                valors[0] = nouValor;
              });
            },
          ),
          Cursor(
            titol: "Verd:",
            valor: valors[1],
            colCurs: ColorsApp.colCursors[1],
            siCanvia: (nouValor) {
              setState(() {
                valors[1] = nouValor;
              });
            },
          ),
          Cursor(
            titol: "Blau:",
            valor: valors[2],
            colCurs: ColorsApp.colCursors[2],
            siCanvia: (nouValor) {
              setState(() {
                valors[2] = nouValor;
              });
            },
          ),
          MostraColor(compColor: valors),
          BotoSeguir(vals: valors, textBoto: "Continuar...", retorn: false),
        ],
      ),
    );
  }
}

pant_resultat.dart
import 'package:flutter/material.dart';
import 'package:selector_color/components/boto_seguir.dart';
import 'package:selector_color/components/mostra_valors.dart';
import 'package:selector_color/components/mostra_contrast.dart';
import 'package:selector_color/core/colors.dart';
import 'package:selector_color/core/funcions.dart';
class PantResultat extends StatefulWidget {
  final List<double> compon;
  const PantResultat({super.key, required this.compon});
  @override
  State<PantResultat> createState() => _PantResultatState();
}

class _PantResultatState extends State<PantResultat> {
  @override
  Widget build(BuildContext context) {
    List<int> colorIntRGB  = intRGBfromDouble(widget.compon);
    Color colorTriat = colFromList(colorIntRGB);
    Color colorComp = colFromList(intRGBCompl(colorIntRGB));
    return Scaffold(
      appBar: AppBar(
        title: Text("Color triat"),
        backgroundColor: ColorsApp.primari,
        foregroundColor: ColorsApp.text,
      ),
      backgroundColor: ColorsApp.fons,
      body: Column(
        children: [
          MostraValors(
            txtRGB: txtListFromInt(colorIntRGB),
            hexRGB: hexFromInt(colorIntRGB),
            txtRGBcomp: txtListFromInt(intRGBCompl(colorIntRGB)),
            hexRGBcomp: hexFromInt(intRGBCompl(colorIntRGB)),
          ),
          MostraContrast(colTriat: colorTriat, colCompl: colorComp),
          BotoSeguir(vals: [0, 0, 0], textBoto: "Tornar", retorn: true),
        ],
      ),
    );
  }
}

Carpeta components

cursor.dart
import 'package:flutter/material.dart';
import 'package:selector_color/core/colors.dart';
import 'package:selector_color/core/estils.dart';
class Cursor extends StatefulWidget {
  final String titol;
  final double valor;
  final Color colCurs;
  final Function(double) siCanvia;
  const Cursor({
    super.key,
    required this.titol,
    required this.valor,
    required this.colCurs,
    required this.siCanvia,
  });

  @override
  State<Cursor> createState() => _CursorState();
}

class _CursorState extends State<Cursor> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.all(20.0),
      child: Column(
        children: [
          Row(
            children: [
              Text(widget.titol, style: Estils.estilTextCursors),
              Spacer(),
              Text(
                widget.valor.toStringAsFixed(0),
                style: Estils.estilTextCursors,
              ),
            ],
          ),
          Slider(
            value: widget.valor, min: 0, max: 255, divisions: 255,
            activeColor: widget.colCurs,
            inactiveColor: ColorsApp.primari,
            padding: const EdgeInsets.only(left: 4, right: 4, top: 12, bottom: 12),
            onChanged: (valorNou) {
              setState(() {
                widget.siCanvia(valorNou);
              });
            },
          ),
        ],
      ),
    );
  }
}

mostra_color.dart
import 'package:flutter/material.dart';
class MostraColor extends StatefulWidget {
  final List<double> compColor;
  const MostraColor({super.key, required this.compColor});

  @override
  State<MostraColor> createState() => _MostraColorState();
}

class _MostraColorState extends State<MostraColor> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.only(bottom: 20, left: 20, right: 20),
        child: Container(
          width: double.infinity,
          decoration: BoxDecoration(
            color: Color.fromARGB(
              255,
              widget.compColor[0].toInt(),
              widget.compColor[1].toInt(),
              widget.compColor[2].toInt(),
            ),
            borderRadius: BorderRadius.circular(12),
          ),
        ),
      ),
    );
  }
}

boto_seguir.dart
import 'package:flutter/material.dart';
import 'package:selector_color/core/colors.dart';
import 'package:selector_color/core/estils.dart';
import 'package:selector_color/screens/pant_resultat.dart';
class BotoSeguir extends StatefulWidget {
  final List<double> vals;
  final String textBoto;
  final bool retorn;
  const BotoSeguir({super.key, required this.vals, required this.textBoto, required this.retorn});

  @override
  State<BotoSeguir> createState() => _BotoSeguirState();
}

class _BotoSeguirState extends State<BotoSeguir> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(left: 20, right: 20, bottom: 40),
      child: SizedBox(
        width: double.infinity,
        child: ElevatedButton(
          onPressed: () {
            if(widget.retorn){
              Navigator.pop(context);
            } else {
              Navigator.push(context, 
              MaterialPageRoute(builder: (context) => PantResultat(compon: widget.vals)));
            }
          },
          style: ButtonStyle(
            shape: WidgetStateProperty.all(
              RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
            ),
            backgroundColor: WidgetStateProperty.all(ColorsApp.primari),
          ),
          child: Text(widget.textBoto, style: Estils.estilTextBotons),
        ),
      ),
    );
  }
}

mostra_valors.dart
import 'package:flutter/material.dart';
import 'package:selector_color/core/colors.dart';
import 'package:selector_color/core/estils.dart';
class MostraValors extends StatefulWidget {
  final String txtRGB;
  final String hexRGB;
  final String txtRGBcomp;
  final String hexRGBcomp;
  const MostraValors({super.key, required this.txtRGB, required this.hexRGB, 
    required this.txtRGBcomp, required this.hexRGBcomp});

  @override
  State<MostraValors> createState() => _MostraValorsState();
}

class _MostraValorsState extends State<MostraValors> {
  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(top: 20, left: 20, right: 20),
      child: Container(
        width: double.infinity,
        alignment: Alignment.center,
        decoration: BoxDecoration(
          color: ColorsApp.primari,
          borderRadius: BorderRadius.circular(12)
        ),
        child: Padding(
          padding: const EdgeInsets.all(12),
          child: Column(
            children: [
              Text("El color és ${widget.txtRGB}", style: Estils.estilTextNormal),
              Text("En hexadecimal és ${widget.hexRGB}", style: Estils.estilTextNormal),
              SizedBox(height: 12,),
              Text("El complementari és ${widget.txtRGBcomp}", style: Estils.estilTextNormal),
              Text("En hexadecimal és ${widget.hexRGBcomp}", style: Estils.estilTextNormal),
              SizedBox(height: 12,),
              Text("Mira la combinació en el requadre següent", style: Estils.estilTextNormal),
            ],
          ),
        ),
      ),
    );
  }
}

mostra_contrast.dart
import 'package:flutter/material.dart';
class MostraContrast extends StatefulWidget {
  final Color colTriat;
  final Color colCompl;
  const MostraContrast({super.key, required this.colTriat, required this.colCompl});

  @override
  State<MostraContrast> createState() => _MostraContrastState();
}

class _MostraContrastState extends State<MostraContrast> {
  @override
  Widget build(BuildContext context) {
    return Expanded(
      child: Padding(
        padding: const EdgeInsets.all(20),
        child: Container(width: double.infinity,
          alignment: Alignment.center,
          decoration: BoxDecoration(color: widget.colTriat,
            borderRadius: BorderRadius.circular(12),
          ),
          child: Column(
            children: [
              Spacer(),
              Container(width: 200, height: 150,
                alignment: Alignment.center,
                decoration: BoxDecoration(color: widget.colCompl,
                  borderRadius: BorderRadius.circular(12),
                ),
              ),
              Spacer(),
            ],
          ),
        ),
      ),
    );
  }
}

Carpeta core

colors.dart
import 'dart:ui';
class ColorsApp {
  static const Color fons = Color(0xFF444444);
  static const Color primari = Color(0xFF7F7F7F);
  static const Color text = Color(0xFFFFFFFF);
  static List<Color> colCursors = [Color(0xFFFF0000), Color(0xFF00FF00), Color(0xFF0000FF)];
}

estils.dart
import 'package:flutter/material.dart';
import 'package:selector_color/core/colors.dart';
class Estils {
  static const TextStyle estilTextNormal = TextStyle(
    color: ColorsApp.text,
    fontSize: 14,
    fontWeight: FontWeight.normal,
  );
  static const TextStyle estilTextCursors = TextStyle(
    color: ColorsApp.text,
    fontSize: 18,
    fontWeight: FontWeight.bold,
  );
  static const TextStyle estilTextBotons = TextStyle(
    color: ColorsApp.text,
    fontSize: 22,
    fontWeight: FontWeight.bold,
  );
}

funcions.dart
import 'dart:ui';
// Converteix una llista de tres reals en una de tres enters
List<int> intRGBfromDouble(List<double> rebut){
  List<int> resposta  = [0, 0, 0];
  for(int i = 0; i < 3; i++){
    resposta[i] = rebut[i].toInt();
  }
  return resposta;
}

// Agafa una llista de tres enters que codifiquen un color i 
//   en genera el color corresponent
Color colFromList(List<int> rebut){
  return Color.fromARGB(255, rebut[0], rebut[1], rebut[2]);
}

// Agafa una llista de tres enters que codifiquen un color i 
//   en genera una nova amb el color complementari
List<int> intRGBCompl(List<int> rebut){
  List<int> resposta  = [0, 0, 0];
  for(int i = 0; i < 3; i++){
    resposta[i] = 255 - rebut[i];
  }
  return resposta;
}

// Genera un text que representa un vector de tres components
//   a partir d'una llista entera de tres components
// Resultat: (R, G, B)
String txtListFromInt(List<int> rebut){
  String resposta = "(";
  for(int i = 0; i < 3; i++){
    if(i > 0){  // Posem la coma entre components
      resposta += ", ";
    }
    resposta += rebut[i].toString();
  }
  resposta += ")";
  return resposta;
}

// Genera un text amb la codificació hexadecimal d'un color
//   a partir d'una llista d'enters que el representen
// Resultat: 0xRRGGBB
String hexFromInt(List<int> rebut){
  String resposta = "0x";
  for(int i = 0; i < 3; i++){
    String prov = rebut[i].toRadixString(16);
    if(prov.length == 1){
      resposta += "0";  // Forcem que tingui dos dígits
    }
    resposta += prov.toUpperCase();
  }
  return resposta;
}

 

 

 

 

 

 

 

 

 

 

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