Diferencia entre revisiones de «Flutter StatefulWidget. Conceptos»

De MediaWiki
Ir a la navegación Ir a la búsqueda
Línea 307: Línea 307:
 
<br />
 
<br />
 
===Ejemplo 2===
 
===Ejemplo 2===
 +
 +
* En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
 +
: Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
 +
 +
* '''Objetivo:''' En este ejemplo, disponemos de 3 botones. Cada botón va a llevar un contador de cuantos veces se ha pulsado, y también cuantas veces se han pulsado todos los botones.
 +
: El número de veces pulsado / total, se visualizará en el texto de botón.
 +
 +
 +
[[Imagen:Flutter_dart_exemplo_2_stateful.JPG|250px|center]]
 +
 +
 +
* '''Solución:''' Necesitamos emplear 4 variables. Una para cada botón, y que guardará información de cuantas veces se ha pulsado dicho botón, y otra que guardará la suma de todos los botones pulsados.
 +
 +
:<syntaxhighlight lang="java" enclose="div" highlight="11,12,24-26,36-39,47-50,58-61,41,52,63" >
 +
import 'package:flutter/material.dart';
 +
 +
class Aprender2Page extends StatefulWidget {
 +
  const Aprender2Page({Key? key}) : super(key: key);
 +
 +
  @override
 +
  _Aprender2PageState createState() => _Aprender2PageState();
 +
}
 +
 +
class _Aprender2PageState extends State<Aprender2Page> {
 +
  int _cont1=0, _cont2=0,_cont3=0;
 +
  int _contTotal = 0;
 +
 +
  @override
 +
  Widget build(BuildContext context) {
 +
    return Scaffold(
 +
        appBar: AppBar(
 +
          title: Text('Aprender2 Statefulwidget'),
 +
        ),
 +
        body: Center(
 +
          child: Column(
 +
            mainAxisAlignment: MainAxisAlignment.center,
 +
            children: [
 +
              _boton1(),
 +
              _boton2(),
 +
              _boton3()
 +
            ],
 +
          ),
 +
        )
 +
    );
 +
  }
 +
 +
  Widget _boton1(){
 +
    return TextButton(
 +
        onPressed: () {
 +
          setState(() {
 +
            _cont1++;
 +
            _contTotal++;
 +
          });
 +
        },
 +
        child: Text('Pulsado $_cont1. Total veces $_contTotal')
 +
    );
 +
  }
 +
  Widget _boton2(){
 +
    return TextButton(
 +
        onPressed: () {
 +
          setState(() {
 +
            _cont2++;
 +
            _contTotal++;
 +
          });
 +
        },
 +
        child: Text('Pulsado $_cont2. Total veces $_contTotal')
 +
    );
 +
  }
 +
  Widget _boton3(){
 +
    return TextButton(
 +
        onPressed: () {
 +
          setState(() {
 +
            _cont3++;
 +
            _contTotal++;
 +
          });
 +
        },
 +
        child: Text('Pulsado $_cont3. Total veces $_contTotal')
 +
    );
 +
  }
 +
}
 +
 +
</syntaxhighlight>
 +
 +
 +
 +
* Si analizáis un poco el código es daréis cuenta que no está muy 'optimizado' ya que por cada botón tenemos el mismo código, variando el número de veces que se pulsa ese botón.
 +
: Lo ideal sería, de alguna forma, que el botón 'supiera' cual es la variable contador asociada al mismo.
 +
 +
 +
: ¿ Se os ocurre alguna idea ? :)
 +
 +
:<syntaxhighlight lang="java" enclose="div" highlight="33,37,41,11,24-26" >
 +
import 'package:flutter/material.dart';
 +
 +
class Aprender2Page extends StatefulWidget {
 +
  const Aprender2Page({Key? key}) : super(key: key);
 +
 +
  @override
 +
  _Aprender2PageState createState() => _Aprender2PageState();
 +
}
 +
 +
class _Aprender2PageState extends State<Aprender2Page> {
 +
  List<int> _listaPulsaciones = [0,0,0];
 +
  int _contTotal = 0;
 +
 +
  @override
 +
  Widget build(BuildContext context) {
 +
    return Scaffold(
 +
        appBar: AppBar(
 +
          title: Text('Aprender2 Statefulwidget'),
 +
        ),
 +
        body: Center(
 +
          child: Column(
 +
            mainAxisAlignment: MainAxisAlignment.center,
 +
            children: [
 +
              _boton(0),
 +
              _boton(1),
 +
              _boton(2),
 +
            ],
 +
          ),
 +
        )
 +
    );
 +
  }
 +
 +
  Widget _boton(int posLista){
 +
    return TextButton(
 +
        onPressed: () {
 +
          setState(() {
 +
            _listaPulsaciones[posLista]++;
 +
            _contTotal++;
 +
          });
 +
        },
 +
        child: Text('Pulsado ${_listaPulsaciones[posLista]} Total veces $_contTotal')
 +
    );
 +
  }
 +
}
 +
</syntaxhighlight>
 +
 +
 +
 +
<br />
 +
: '''Posible Solución:''' Una forma (que no la única) con lo que sabemos hasta ahora, podría ser guardar los valores 'locales' de cada botón en una lista. En ese caso, el botón 1 tendría que modificar la posición 0 de la lista, el botón 2, la posición segunda de la lista y el botón 3 la tercera posición. Por lo tanto, cuando llamo a la función que representa el Widget botón, podría enviarle la posición a modificar.
 +
 +
 +
 +
<br />
 +
===Ejemplo 3===
 +
 +
* En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
 +
: Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
 +
 +
* '''Objetivo:''' Al pulsar sobre un elemento de la lista, este queda seleccionado visualmente y una etiqueta muestra el valor seleccionado.
 +
 +
[[Imagen:Flutter_dart_exemplo_1_stateful.JPG|250px|center]]
 +
 +
 +
* '''Solución:''' Los datos de la lista van a estar en un List. Necesitamos guardar el elemento seleccionado (o su posición) para que cuando se 'dibuje' comprobar si el elemeto que se está dibujando es el elemento seleccionado, y en ese caso, poner un color de fondo al mismo.
 +
 +
 +
:<syntaxhighlight lang="java" enclose="div" highlight="31-60,21-23" >
 +
 +
</syntaxhighlight>
 +
 +
 +
 +
<br />
 +
===Ejemplo 3===
  
 
* En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
 
* En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
Línea 312: Línea 479:
  
 
* En este ejemplo, al pulsar sobre un elemento de la lista, este queda seleccionado visualmente y una etiqueta muestra el valor seleccionado.
 
* En este ejemplo, al pulsar sobre un elemento de la lista, este queda seleccionado visualmente y una etiqueta muestra el valor seleccionado.
 +
[[Imagen:Flutter_dart_exemplo_1_stateful.JPG|250px|center]]
  
 
:<syntaxhighlight lang="java" enclose="div" highlight="31-60,21-23" >
 
:<syntaxhighlight lang="java" enclose="div" highlight="31-60,21-23" >
Línea 419: Línea 587:
  
 
<br />
 
<br />
 +
 
==Ejercicios propuestos==
 
==Ejercicios propuestos==
  

Revisión del 18:15 4 nov 2021

Introducción

  • Más información en:


  • Hasta ahora hemos usado los StatelessWidget para todo.
Este tipo de Widget:
  • No permite guardar ningún tipo de dato en forma de variable y cuando definimos algo a nivel de clase siempre debe estar asociado al modificador final o static const.
Si no se pone dicho modificador, no impide compilar la aplicación y aparecerá un Warning en la definición de la Clase (el nombre de la clase aparecerá subrayada).
Un ejemplo de uso sería cuando tenemos un formulario y queremos guardar lo escrito por el usuario en una variable. Esto no lo podríamos realizar con este tipo de Widget.
  • No se pueden 'redibujar' para hacer que reflejen un cambio que pueda darse por programación. Imagináos el caso de que busquéis datos por Internet y se carguen nuevos datos en la lista en la que se basa un ListView para visualizar el contenido...


En Flutter, no funciona igual que la programación tradicional con entornos gráficos, en los que se tiene una pantalla con componentes (cajas de texto, listas,...) y cambiando sus valores automáticamente se reflejan dichos cambios en el componente visual.
En Flutter, los componentes visuales (Widget´s) si visualizan en base a los datos definidos en el Widget. Si dichos datos son cambiados, es necesario redibujar el Widget para que se vuelva a visualizar con los datos modificados.
Así, si por ejemplo, tengo que una etiqueta (Widget Text) visualiza el contenido de una variable, y cambio el valor de dicha variable, es necesario redibujar el Widget etiqueta para que vuelva a visualizar el contenido cambiado.



Minuto 10: Indico que se debe devolver un EjemploStateful cuando debería ser un _EjemploStatefulState


Código explicativo del vídeo.

import 'package:flutter/material.dart';

class EjemploStateLess extends StatelessWidget {
  int _valor = 0;   // Debería ser final ya que un StatelessWidget está definido como inmutable

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('StateLessWidget'),
        ),
        body: _boton()
    );
  }

  Widget _boton(){
    return Center(child: TextButton(child:Text('Presiona $_valor'),
                                    onPressed: (){
                                        print('pulsado $_valor');
                                        _valor = _valor + 1 ;       // Aunque su valor se modifica nunca podríamos 'visualizar' su contenido actualizado.
                                    },
                                    style: TextButton.styleFrom(backgroundColor: Colors.amber),
                                    )
                  );

  }
}



class EjemploStateful extends StatefulWidget {

  @override
  _EjemploStatefulState createState() => _EjemploStatefulState();
}

class _EjemploStatefulState extends State<EjemploStateful> {
    int _valor = 10;

    @override
    Widget build(BuildContext context) {
      return Scaffold(
          appBar: AppBar(
            title: Text('appbarTitle'),
          ),
          body: _boton()
      );

    }
    Widget _boton(){
      return Center(child: TextButton(child:Text('Presiona valores $_valor'),
        onPressed: (){
          print('pulsado $_valor');
          setState(() {
            _valor++;
          });
        },
        style: TextButton.styleFrom(backgroundColor: Colors.amber),
        )
      );

    }
}



Accediendo a las propiedes del StatefulWidget desde el State

  • Cuando definimos una propiedad local dentro del StatefulWidget, podremos acceder a dicha variable dentro de la clase State empleado la palabra widget.propiedad.
Veamos un ejemplo en el que definimos la variable contador dentro del StatefulWidget botón.


import 'package:flutter/material.dart';

class EjemploStateLess extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('StateLessWidget'),
        ),
        body: Column(
          children: [
            _BotonStateful()  // Recordar que esto es equivalente a new _BotonStateless
          ],
        )
    );
  }
}

class _BotonStateful extends StatefulWidget {
  final colorAzul = Colors.blue;   
  @override
  _BotonStatefulState createState() => _BotonStatefulState();
}

class _BotonStatefulState extends State<_BotonStateful> {
  int _contador = 0;

  @override
  Widget build(BuildContext context) {
    return Center(child: TextButton(child:Text('Botón Stateful ${widget._contador}'),
      style: TextButton.styleFrom(backgroundColor: widget.colorAzul), onPressed: () { setState(() {
        _contador++;  
      }); },
    )
    );
  }
}


  • Nota: Lo 'normal' es que las constantes estén definidas en el Stateful (partes invariantes) y las variables en el State asociado.


Combinando Widgets

  • Indicar que dentro de una clase podemos tener diferentes Widget de tipo Stateless o Stateful.
En el siguiente ejemplo, dentro de un StatelessWidget creo dos Widgets botones, uno de tipo StatelessWidget y otro de tipo StatefulWidget.
Ya veremos posteriormente como podemos pasar datos entre Widgets y entre pantallas diferentes.
En el ejemplo creo una clase (Datos) que guarda el valor que quiero enviar a los dos botones.
Al pulsar sobre el StatelesWidget, puedo incrementar el valor de dicha variable, pero no puedo redibujar el Widget, por lo que el contador aumentará pero no se visualizará hasta que pulse sobre el StatefulWidget el cual se redibujará con el nuevo valor.
Flutter dart stateful 1.JPG


import 'package:flutter/material.dart';

class _Datos{
  int valor = 0;
}
final dato = new _Datos();


class EjemploStateLess extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('StateLessWidget'),
        ),
        body: Column(
          children: [
            _BotonStateless(),    // Recordar que esto es equivalente a new _BotonStateless
            _BotonStateful()
          ],
        )
    );
  }
}


class _BotonStateful extends StatefulWidget {
  @override
  _BotonStatefulState createState() => _BotonStatefulState();
}

class _BotonStatefulState extends State<_BotonStateful> {

  @override
  Widget build(BuildContext context) {
    return Center(child: TextButton(child:Text('Botón Stateful ${dato.valor}'),
      style: TextButton.styleFrom(backgroundColor: Colors.amber), onPressed: () { setState(() {
        dato.valor++;
      }); },
    )
    );
  }
}



class _BotonStateless extends StatelessWidget {

  @override
  Widget build(BuildContext context) {
    return Center(child: TextButton(child:Text('Botón Stateless ${dato.valor}'),
        style: TextButton.styleFrom(backgroundColor: Colors.amber), onPressed: () { dato.valor++; },
      )
    );

  }
}



Ejemplos de uso

  • Voy a explicar a continuación varios ejemplos que irán completando la explicación anterior...
  • En todos los ejemplos, salvo que se indique lo contrario, debéis hacer lo mismo:
Creamos una nueva página en la carpeta pages/stateful/aprender de nombre aprenderNUM_page.dart (crear los directorios dentro de lib si no están creados previamente). NUM es el número de ejemplo.
En todas las páginas haremos lo mismo:
  • Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
  • Creamos una clase (AprenderNUMPage) que derive de StatefulWidget. Se creará (si lo hacéis con un Snippet) una clase asociada que deriva de State. NUM es el número de ejemplo.
  • Modificamos la clase State y en su métod build hacemos que devuelva un Scaffold con una Appbar (hacerlo con un Snippet)



Ejemplo 1

  • En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
  • Objetivo: Modificar el tamaño (ancho) de un container el pulsar sobre el botón.
Flutter dart exemplo 1 stateful.JPG


Solución: Para lograr este objetivo, necesitamos emplear una variable (ya que su valor va a aumentar al pulsar el botón) y asociar dicha variable al ancho del contenedor.
Por lo tanto, al pulsar sobre el botón, es necesario modificar el valor de la variable y redibujar el contenedor (en este momento no sabemos hacer eso, sabemos redibujar el StatefulWidget que es la pantalla entera, y por tanto se va a redibujar el botón, el contenedor, la AppBar,es decir, toda la pantalla.


import 'package:flutter/material.dart';
/**
 * Neste exemplo aprendemos a diferenza entre Stateless e Stateful
 * Temos que entender como funcionan os Widgets en Flutter.
 */

class Aprender1Page extends StatefulWidget {
  const Aprender1Page({Key? key}) : super(key: key);

  @override
  _Aprender1PageState createState() => _Aprender1PageState();
}

class _Aprender1PageState extends State<Aprender1Page> {
  double _ancho = 50;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Aprender1 Statefulwidget'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              Container(
                padding: EdgeInsets.all(10),
                width: _ancho,
                height: 50,
                color: Colors.indigo,
              ),
              TextButton(
                child: Text('PRESIONAME'),
                style: TextButton.styleFrom(backgroundColor: Colors.black),
                onPressed: () {
                  setState(() {
                    _ancho+=20;
                  });
                },
              )
            ],
          ),
        )
    );
  }
}



Ejemplo 2

  • En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
  • Objetivo: En este ejemplo, disponemos de 3 botones. Cada botón va a llevar un contador de cuantos veces se ha pulsado, y también cuantas veces se han pulsado todos los botones.
El número de veces pulsado / total, se visualizará en el texto de botón.


Flutter dart exemplo 2 stateful.JPG


  • Solución: Necesitamos emplear 4 variables. Una para cada botón, y que guardará información de cuantas veces se ha pulsado dicho botón, y otra que guardará la suma de todos los botones pulsados.
import 'package:flutter/material.dart';

class Aprender2Page extends StatefulWidget {
  const Aprender2Page({Key? key}) : super(key: key);

  @override
  _Aprender2PageState createState() => _Aprender2PageState();
}

class _Aprender2PageState extends State<Aprender2Page> {
  int _cont1=0, _cont2=0,_cont3=0;
  int _contTotal = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Aprender2 Statefulwidget'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              _boton1(),
              _boton2(),
              _boton3()
            ],
          ),
        )
    );
  }

  Widget _boton1(){
    return TextButton(
        onPressed: () {
          setState(() {
            _cont1++;
            _contTotal++;
          });
        },
        child: Text('Pulsado $_cont1. Total veces $_contTotal')
    );
  }
  Widget _boton2(){
    return TextButton(
        onPressed: () {
          setState(() {
            _cont2++;
            _contTotal++;
          });
        },
        child: Text('Pulsado $_cont2. Total veces $_contTotal')
    );
  }
  Widget _boton3(){
    return TextButton(
        onPressed: () {
          setState(() {
            _cont3++;
            _contTotal++;
          });
        },
        child: Text('Pulsado $_cont3. Total veces $_contTotal')
    );
  }
}


  • Si analizáis un poco el código es daréis cuenta que no está muy 'optimizado' ya que por cada botón tenemos el mismo código, variando el número de veces que se pulsa ese botón.
Lo ideal sería, de alguna forma, que el botón 'supiera' cual es la variable contador asociada al mismo.


¿ Se os ocurre alguna idea ? :)
import 'package:flutter/material.dart';

class Aprender2Page extends StatefulWidget {
  const Aprender2Page({Key? key}) : super(key: key);

  @override
  _Aprender2PageState createState() => _Aprender2PageState();
}

class _Aprender2PageState extends State<Aprender2Page> {
  List<int> _listaPulsaciones = [0,0,0];
  int _contTotal = 0;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Aprender2 Statefulwidget'),
        ),
        body: Center(
          child: Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: [
              _boton(0),
              _boton(1),
              _boton(2),
            ],
          ),
        )
    );
  }

  Widget _boton(int posLista){
    return TextButton(
        onPressed: () {
          setState(() {
            _listaPulsaciones[posLista]++;
            _contTotal++;
          });
        },
        child: Text('Pulsado ${_listaPulsaciones[posLista]} Total veces $_contTotal')
    );
  }
}



Posible Solución: Una forma (que no la única) con lo que sabemos hasta ahora, podría ser guardar los valores 'locales' de cada botón en una lista. En ese caso, el botón 1 tendría que modificar la posición 0 de la lista, el botón 2, la posición segunda de la lista y el botón 3 la tercera posición. Por lo tanto, cuando llamo a la función que representa el Widget botón, podría enviarle la posición a modificar.



Ejemplo 3

  • En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
  • Objetivo: Al pulsar sobre un elemento de la lista, este queda seleccionado visualmente y una etiqueta muestra el valor seleccionado.
Flutter dart exemplo 1 stateful.JPG


  • Solución: Los datos de la lista van a estar en un List. Necesitamos guardar el elemento seleccionado (o su posición) para que cuando se 'dibuje' comprobar si el elemeto que se está dibujando es el elemento seleccionado, y en ese caso, poner un color de fondo al mismo.




Ejemplo 3

  • En este ejemplo, partimos que todo nuestro Widget Scaffold es un StatefulWidget.
Dentro del mismo, todos los Widget que definamos 'localmente', van poder llamar al método setState para redibujar el StatefulWidget y por tanto redibujará toda la pantalla.
  • En este ejemplo, al pulsar sobre un elemento de la lista, este queda seleccionado visualmente y una etiqueta muestra el valor seleccionado.
Flutter dart exemplo 1 stateful.JPG



Ejemplo contador

  • Podemos analizar ahora el ejemplo 'Hola Mundo' que aparece cuando se instala Flutter y que podemos visualizar en la página dartpad.dev



Ejemplo de varios StatefulWidget

En todas las páginas haremos lo mismo:
  • Importamos la librería de 'material' (recordar que existe un snippet que lo hace automático).
  • Creamos una clase que derive de StatelessWidget (al hacerlo será necesario implementar el método build, ya os da un aviso el Android Studio).
  • Dentro del método build, retornamos un widget Scaffold (recordar que existe un snippet que lo hace automático).


  • En este ejemplo podemos ver como disponemos de 3 Containers, y al pulsarlos, la variable local a dichos contenedores se incrementa.
Dentro del child del Scaffold retornamos un widget Row, donde situaremos los 3 contenedores.


Flutter dart stateful 2.JPG


Para controlar el evento de pulsar sobre un contenedor hago uso de la clase InkWell que permite tener un efecto al pulsar sobre el contenedor.
import 'package:flutter/material.dart';

class VariosStateFull extends StatelessWidget {
  const VariosStateFull({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Varios StatefulWidget'),
        ),
        body: Center(
          child: _variosContenedores(),
        ));
  }

  Widget _variosContenedores(){
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Contenedor(color: Colors.green),
        Contenedor(color: Colors.red),
        Contenedor(color: Colors.yellow),

      ],
    );
  }

}

class Contenedor extends StatefulWidget {
  final Color color;
  const Contenedor({Key? key, required this.color}) : super(key: key);

  @override
  _ContenedorState createState() => _ContenedorState();
}

class _ContenedorState extends State<Contenedor> {

  int _contador=0;
  _ContenedorState(){

  }
  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        child: Text('$_contador'),
        color: widget.color,
        width: 50,
        height: 50,
        margin: EdgeInsets.all(12.0),
      ),
      onTap: (){ setState(() {
        _contador++;
      });},
    );
  }
}





Ejercicios propuestos

  • Crea una variable global que guarde en un lista los valores de los tres contenedores.
Haz que cada contenedor esté identificado por un id (0,1,2) que se corresponda con la posición de la lista a la que tendrá que acceder a modificar su valor.
En base al id (0,1,2) haz que al presionar el contenedor, aumente el valor del elemento de la lista y que se visualice en el texto que hay en el interior.
¿ Cómo harías para que en el caso de que se actualizara en contador de todos los contenedores al pulsar en cualquiera de ellos ?



Solución ejercicio propuesto:

import 'package:flutter/material.dart';

var datos = <int>[1,2,3];

class VariosStateFull extends StatelessWidget {
  const VariosStateFull({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: Text('Varios StatefulWidget'),
        ),
        body: Center(
          child: _variosContenedores(),
        ));
  }

  Widget _variosContenedores(){
    return Row(
      mainAxisAlignment: MainAxisAlignment.center,
      children: [
        Contenedor(color: Colors.green,id: 0),
        Contenedor(color: Colors.red, id: 1),
        Contenedor(color: Colors.yellow,id: 2),

      ],
    );
  }

}

class Contenedor extends StatefulWidget {
  final Color color;
  final int id;
  const Contenedor({Key? key, required this.color,required this.id}) : super(key: key);

  @override
  _ContenedorState createState() => _ContenedorState();
}

class _ContenedorState extends State<Contenedor> {

  int _contador=0;
  _ContenedorState(){

  }
  @override
  Widget build(BuildContext context) {
    return InkWell(
      child: Container(
        child: Text('${datos[widget.id]}'),
        color: widget.color,
        width: 50,
        height: 50,
        margin: EdgeInsets.all(12.0),
      ),
      onTap: (){ setState(() {
        datos[widget.id]++;
      });},
    );
  }
}


Pregunta: ¿ Cómo harías para que en el caso de que se actualizara en contador de todos los contenedores al pulsar en cualquiera de ellos ?
Respuesta: Habría que crear un único StatefulWidget que 'envuelva' a los 3 contenedores.



Enlace a la página principal de la UD4

Enlace a la página principal del curso




-- Ángel D. Fernández González -- (2021).