es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Cambiar estado de un botón clicado dentro de una lista StreamBuilder en Flutter.

Tengo un StreamBuilder que me devuelve un ListView de elementos.

Para cada elemento, también tengo un botón ElevatedButton.

ElevatedButton(
  onPressed: () {
    setState(() {
      pressGeoON = !pressGeoON;
      if (pressGeoON == true) {
        favoriteDataList.add(snapshot
            .data?.docs[index].id);
      } else {
        favoriteDataList.removeWhere(
            (item) =>
                item ==
                snapshot.data
                    ?.docs[index].id);
      }
    });
  },
  style: ButtonStyle(
    backgroundColor:
        MaterialStateProperty.all<color>(
      Colors.deepPurple,
    ),
  ),
  child: Icon(
    Icons.favorite,
    color: pressGeoON
        ? Colors.blue
        : Colors.red,
  ),
)

Estoy intentando cambiar el estado solo del botón clicado, pero hasta ahora con mi código siempre cambia el estado de todos los botones dentro de la lista.
¿Cómo puedo cambiar el estado solo del botón clicado y no de todos ellos?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Una forma de resolver este problema es crear un StatefulWidget separado para cada elemento de la ListView. De esta manera, puedes mantener el estado de cada botón por separado.

    Crea un nuevo StatefulWidget para tus elementos:

    class MyItem extends StatefulWidget {
      final DocumentSnapshot document;
    
      const MyItem({Key key, this.document}) : super(key: key);
    
      @override
      _MyItemState createState() => _MyItemState();
    }
    

    En el estado de MyItem, mantén el estado del botón:

    class _MyItemState extends State<myitem> {
      bool _isFavorited = false;
    
      @override
      Widget build(BuildContext context) {
        return ListTile(
            title: Text(widget.document.data()['title']),
            trailing: ElevatedButton(
              onPressed: () {
                setState(() {
                  _isFavorited = !_isFavorited; // alterna el valor
                  if (_isFavorited) {
                    favoriteDataList.add(widget.document.id);
                  } else {
                    favoriteDataList.remove(widget.document.id);
                  }
                });
              },
              style: ButtonStyle(
                backgroundColor: MaterialStateProperty.all<color>(
                  Colors.deepPurple,
                ),
              ),
              child: Icon(
                Icons.favorite,
                color: _isFavorited ? Colors.blue : Colors.red,
              ),
            ));
      }
    }
    

    Envuelve tu constructor de ListView con un StreamBuilder:

    StreamBuilder(
      stream: myStream,
      builder: (BuildContext context, AsyncSnapshot<querysnapshot> snapshot) {
        if (!snapshot.hasData) {
          return Center(child: CircularProgressIndicator());
        }
        return ListView.builder(
          itemCount: snapshot.data.docs.length,
          itemBuilder: (context, index) {
            final document = snapshot.data.docs[index];
            return MyItem(key: ValueKey(document.id), document: document);
          },
        );
      },
    ),
    

    Al utilizar claves únicas para cada widget MyItem (ValueKey(document.id)), Flutter reconocerá cada elemento como separado y su estado no afectará a los demás elementos.

Comments are closed.