En la versió que hem presentat per a aquesta aplicació, teníem dues pantalles. Es podria obtenir un resultat molt similar fent servir una única pantalla i controlant, amb blocs de visibilitat, quins elements es veuen en cada moment.
Amb aquesta versió alternativa, la major part dels elements (cursors i requadres) requereixen petites modificacions; els canvis més importants es produeixen a la pantalla principal i, especialment, en el botó, que ara canvia de funcionament.
En els cursors i requadres haurem d'afegir un paràmetre addicional, que hem anomenat esVeu, que defineix si l'element és visible o no. El giny principal de l'element el posarem dins d'un bloc de visibilitat.
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 bool esVeu;
final Function(double) siCanvia;
const Cursor({super.key, required this.titol, required this.valor,
required this.colCurs, required this.siCanvia, required this.esVeu});
@override
State<Cursor> createState() => _CursorState();
}
class _CursorState extends State<Cursor> {
@override
Widget build(BuildContext context) {
return Visibility(
visible: widget.esVeu,
child: 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;
final bool esVeu;
const MostraColor({super.key, required this.compColor, required this.esVeu});
@override
State<MostraColor> createState() => _MostraColorState();
}
class _MostraColorState extends State<MostraColor> {
@override
Widget build(BuildContext context) {
return Visibility(
visible: widget.esVeu,
child: 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),
),
),
),
),
);
}
}
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;
final bool esVeu;
const MostraValors({super.key, required this.txtRGB, required this.hexRGB,
required this.txtRGBcomp, required this.hexRGBcomp, required this.esVeu});
@override
State<MostraValors> createState() => _MostraValorsState();
}
class _MostraValorsState extends State<MostraValors> {
@override
Widget build(BuildContext context) {
return Visibility(
visible: widget.esVeu,
child: 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;
final bool esVeu;
const MostraContrast({super.key, required this.colTriat, required this.colCompl, required this.esVeu});
@override
State<MostraContrast> createState() => _MostraContrastState();
}
class _MostraContrastState extends State<MostraContrast> {
@override
Widget build(BuildContext context) {
return Visibility(
visible: widget.esVeu,
child: 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(),
],
),
),
),
),
);
}
}
En el botó hi ha més canvis. Ara ja no li hem de passar les components de color (perquè no les haurà de traspassar a la segona pantalla) ni necessitem el paràmetre retorn. D'altra banda, li haurem d'afegir una funció, que hem anomenat canvi, com a paràmetre; ja que quan es premi el botó es modificaran variables que necessitem a la pantalla principal.
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 bool res;
final Function canvi;
//final List<double> vals;
//final String textBoto;
//final bool retorn;
const BotoSeguir({super.key, required this.canvi, required this.res});
@override
State<BotoSeguir> createState() => _BotoSeguirState();
}
class _BotoSeguirState extends State<BotoSeguir> {
@override
Widget build(BuildContext context) {
String txtBtn = "";
if(widget.res){
txtBtn = "Tornar";
} else {
txtBtn = "Continuar...";
}
return Padding(
padding: const EdgeInsets.only(left: 20, right: 20, bottom: 40),
child: SizedBox(
width: double.infinity,
child: ElevatedButton(
onPressed: () {
widget.canvi();
},
style: ButtonStyle(
shape: WidgetStateProperty.all(
RoundedRectangleBorder(borderRadius: BorderRadius.circular(12)),
),
backgroundColor: WidgetStateProperty.all(ColorsApp.primari),
),
child: Text(txtBtn, style: Estils.estilTextBotons),
),
),
);
}
}
Finalment, ens falta la pantalla principal. Haurem de crear una variable (que anomenem resultats) que indica si estem a la part de triar el color o a la de mostrar el resultat. Hem traslladat a aquesta pantalla els dos requadres que hi havia a l'antiga pantalla de resultats i les variables que hi tenien relació. A tots els ginys hem afegit la variable esVeu com a paràmetre. La funció del botó, ara definida a la pantalla principal, només canvia l'estat de la variable resultats. Per descomptat, el fitxer pant_resultat.dart ja es pot esborrar del projecte.
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/components/mostra_contrast.dart'; import 'package:selector_color/components/mostra_valors.dart'; import 'package:selector_color/core/colors.dart'; import 'package:selector_color/core/funcions.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];
bool resultats = false;
@override
Widget build(BuildContext context) {
List<int> colorIntRGB = intRGBfromDouble(valors);
Color colorTriat = colFromList(colorIntRGB);
Color colorComp = colFromList(intRGBCompl(colorIntRGB));
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], esVeu: !resultats,
siCanvia: (nouValor) {
setState(() {valors[0] = nouValor;});
},
),
Cursor(
titol: "Verd:", valor: valors[1], colCurs: ColorsApp.colCursors[1], esVeu: !resultats,
siCanvia: (nouValor) {
setState(() {valors[1] = nouValor;});
},
),
Cursor(
titol: "Blau:", valor: valors[2], colCurs: ColorsApp.colCursors[2], esVeu: !resultats,
siCanvia: (nouValor) {
setState(() {valors[2] = nouValor;});
},
),
MostraColor(compColor: valors, esVeu: !resultats),
MostraValors(
txtRGB: txtListFromInt(colorIntRGB),
hexRGB: hexFromInt(colorIntRGB),
txtRGBcomp: txtListFromInt(intRGBCompl(colorIntRGB)),
hexRGBcomp: hexFromInt(intRGBCompl(colorIntRGB)), esVeu: resultats
),
MostraContrast(colTriat: colorTriat, colCompl: colorComp, esVeu: resultats),
BotoSeguir(res: resultats, canvi: () {
setState(() {
resultats = !resultats;
});
}),
],
)
);
}
}
La nova versió de l'aplicació funciona de la mateixa manera que l'anterior. L'única diferència és que la barra de l'aplicació és sempre la mateixa i, per tant, no canvia el text quan es mostren els resultats. Tampoc hi ha el botó de tornar enrere que abans sortia a la barra de l'aplicació de la pantalla de resultats.
Podem aconseguir un aspecte força semblant fent que el text de la barra de l'aplicació depengui de la variable resultats i posant-hi una icona que només es veu quan s'està en la vista de resultats.
...
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (BuildContext context){
return Visibility(
visible: resultats,
child: IconButton(
onPressed: () {
setState(() {resultats = false;});},
icon: Icon(Icons.arrow_back)
),
);
}),
title: Text(resultats ? "Color triat" : "Tria un color"),
backgroundColor: ColorsApp.primari,
foregroundColor: ColorsApp.text,
),
backgroundColor: ColorsApp.fons,
body: Column(
...

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