Search code examples
flutterflutter-provider

Why when marking an icon as a favorite, they are all marked at the same time?


enter image description here

As you can see in the image, the problem is that when I mark an icon as a favorite, the others also do so, and the truth is that I don't know how to make each marker independent. I am handling the states with provider. here the model.

class HeartIconState with ChangeNotifier {
  Icon _hearticon = const Icon(
    Icons.favorite_border,
  );
  Icon get hearticon => _hearticon;

  void changeHeart() {
    if (_hearticon.icon == Icons.favorite_border) {
      _hearticon = const Icon(
        Icons.favorite,
      );
    } else {
      _hearticon = const Icon(
        Icons.favorite_border,
      );
    }
    notifyListeners();
  }

  set hearticon(Icon value) {
    _hearticon = value;
    notifyListeners();
  }
}

here the way he calls them.

Align(
alignment: Alignment.bottomRight,
child: IconButton(
icon: Heart.hearticon,
onPressed: Heart.changeHeart,
color: Colors.red,
                      ),
                    ),

I will also put the whole card in case someone is suddenly interested.

Card(
        elevation: 5.0,
        clipBehavior: Clip.antiAlias,
        shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
        child: InkWell(
          child: Container(
            color: Colors.white,
            width: 200.0,
            height: 250.0,
            child: Column(
              crossAxisAlignment: CrossAxisAlignment.start,
              mainAxisAlignment: MainAxisAlignment.start,
              children: [
                Container(
                    width: 200.0,
                    height: 155.0,
                    child: CachedNetworkImage(
                        fadeInDuration: const Duration(milliseconds: 200),
                        fit: BoxFit.cover,
                        imageUrl: url,
                        placeholder: (context, urlImage) =>
                            Container(color: Colors.grey),
                        errorWidget: (context, urlImage, error) =>
                            Center(child: Container(color: Colors.grey)))),
                Expanded(
                  child: Padding(
                    padding: const EdgeInsets.all(10.0),
                    child: Column(
                      crossAxisAlignment: CrossAxisAlignment.start,
                      mainAxisAlignment: MainAxisAlignment.start,
                      children: [
                        ubicacion != ""
                            ? Text(ubicacion,
                                style: TextStyle(
                                    fontSize: 12.0, color: Colors.grey[600]),
                                maxLines: 1)
                            : Container(),
                        titulo != ""
                            ? Text(titulo,
                                style: const TextStyle(
                                    fontSize: 15.0,
                                    color: Colors.black,
                                    fontWeight: FontWeight.normal),
                                maxLines: 2)
                            : Container(),
                        precio != ""
                            ? Text(precio,
                                style: const TextStyle(
                                    fontSize: 15.0,
                                    color: Colors.black,
                                    fontWeight: FontWeight.normal),
                                maxLines: 1)
                            : Container(),
                        Align(
                          alignment: Alignment.bottomRight,
                          child: IconButton(
                            icon: Heart.hearticon,
                            onPressed: Heart.changeHeart,
                            color: Colors.red,
                          ),
                        ),
                      ],
                    ),
                  ),
                ),
              ],
            ),
          ),
        ),
      ),

Solution

  • Because you use the same icon for all, you have use separate statefull class for each card like this :

    class MyWidget extends StatefulWidget {
      const MyWidget({Key? key}) : super(key: key);
    
      @override
      State<MyWidget> createState() => _MyWidgetState();
    }
    
    class _MyWidgetState extends State<MyWidget> {
      bool isActive = false;
      @override
      Widget build(BuildContext context) {
        return Card(
          elevation: 5.0,
          clipBehavior: Clip.antiAlias,
          shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(8.0)),
          child: InkWell(
            child: Container(
              color: Colors.white,
              width: 200.0,
              height: 250.0,
              child: Column(
                crossAxisAlignment: CrossAxisAlignment.start,
                mainAxisAlignment: MainAxisAlignment.start,
                children: [
                  Container(
                      width: 200.0,
                      height: 155.0,
                      child: CachedNetworkImage(
                          fadeInDuration: const Duration(milliseconds: 200),
                          fit: BoxFit.cover,
                          imageUrl: url,
                          placeholder: (context, urlImage) =>
                              Container(color: Colors.grey),
                          errorWidget: (context, urlImage, error) =>
                              Center(child: Container(color: Colors.grey)))),
                  Expanded(
                    child: Padding(
                      padding: const EdgeInsets.all(10.0),
                      child: Column(
                        crossAxisAlignment: CrossAxisAlignment.start,
                        mainAxisAlignment: MainAxisAlignment.start,
                        children: [
                          ubicacion != ""
                              ? Text(ubicacion,
                                  style: TextStyle(
                                      fontSize: 12.0, color: Colors.grey[600]),
                                  maxLines: 1)
                              : Container(),
                          titulo != ""
                              ? Text(titulo,
                                  style: const TextStyle(
                                      fontSize: 15.0,
                                      color: Colors.black,
                                      fontWeight: FontWeight.normal),
                                  maxLines: 2)
                              : Container(),
                          precio != ""
                              ? Text(precio,
                                  style: const TextStyle(
                                      fontSize: 15.0,
                                      color: Colors.black,
                                      fontWeight: FontWeight.normal),
                                  maxLines: 1)
                              : Container(),
                          Align(
                            alignment: Alignment.bottomRight,
                            child: IconButton(
                              icon: isActive? **first Icon** : **second Icon**,
                              onPressed: () {
                                setState(() {
                                  isActive = !isActive;
                                });
                              },
                              color: Colors.red,
                            ),
                          ),
                        ],
                      ),
                    ),
                  ),
                ],
              ),
            ),
          ),
        );
      }
    }