flutterfavorites

how to activate and deactivate favorite icon in flutter


I want to activate and deactivate favorite icon for every individual item as what I am getting now is to fill that icon but at the same time,it doesnt get deactivated.

bool isPressed=false;
new GestureDetector(
                            onTap: () {
                              setState(() => isPressed = true);
                            },
                            child: Icon(Icons.favorite_sharp,
                                // color: Colors.redAccent,
                                color: (isPressed)
                                    ? Colors.red
                                    : Colors.black12)),

Now activation and deactivation is working but while selecting an individual favorite icon, it is showing all the favorite icon as selected.

ListView.builder(
  itemCount: infoList.length,
  itemBuilder: (BuildContext context, int index) {
    Info info = new Info(
      "${infoList[index].id}",
      "${infoList[index].name}",
      "${infoList[index].image}",
      "${infoList[index].thumb}",
      "${infoList[index].catagory}",
      "${infoList[index].price}",
      "${infoList[index].qty}",
    );
    return new Card(
        margin: EdgeInsets.fromLTRB(5, 0, 5, 5),
        elevation: 5,
        shape: RoundedRectangleBorder(
            borderRadius: BorderRadius.circular(10.0)),
        child: ClipRRect(
            child: ListTile(
                leading: Container(
                    child: Image.network("${infoList[index].image}")),
                title: Text(
                  "${infoList[index].name}",
                  style: TextStyle(
                      fontStyle: FontStyle.normal,
                      fontSize: 14,
                      color: Colors.black),
                ),
                subtitle: Text(
                  "\$ ${infoList[index].price}",
                  style: TextStyle(
                      fontStyle: FontStyle.normal,
                      fontSize: 14,
                      color: Colors.black),
                ),
                trailing: Wrap(
                  spacing: 12,
                  children: [
                    GestureDetector(
                        onTap: () {
                          setState(() => isPressed = !isPressed);
                        },
                        child: Icon(Icons.favorite_sharp,
                            // color: Colors.redAccent,
                            color: (isPressed)
                                ? Colors.red
                                : Colors.black12)),

                    // Icon(
                    //   Icons.add_shopping_cart,
                    //   color: Colors.white,
                    // ),
                  ],
                ),

Solution

  • I just added an ' _ ' to the isPressed variable as it is a good practice to keep such variables as private.

    i.e.

    isPressed -> Public

    _isPressed -> Private

    bool _isPressed = false;
    GestureDetector(
        onTap: () {
               setState(() => _isPressed = !_isPressed);
        },
        child: Icon(Icons.favorite_sharp,
                    color: _isPressed ? Colors.red : Colors.black12)),
    

    For each widget to have it's on selection you'll have to make it into a separate Stateful Widget and then pass it into the ListView.

    Once you've done that now every widget will have it's own state and they can be separately selected / disselected.

    EDIT

    Make the Card Widget into another StateFull widget

    For eg.

    class CardWidget extends StatefulWidget {
    
      final Info info;
      CardWidget(this.info);
      @override
      _CardWidgetState createState() => _CardWidgetState();
    }
    
    class _CardWidgetState extends State<CardWidget> {
      
    bool _isPressed = false;
    
      @override
      Widget build(BuildContext context) {
        return Card(
                margin: EdgeInsets.fromLTRB(5, 0, 5, 5),
                elevation: 5,
                shape: RoundedRectangleBorder(
                    borderRadius: BorderRadius.circular(10.0)),
                child: ClipRRect(
                    child: ListTile(
                        leading: Container(
                            child: Image.network("${widget.info.image}")),
                        title: Text(
                          "${widget.info.name}",
                          style: TextStyle(
                              fontStyle: FontStyle.normal,
                              fontSize: 14,
                              color: Colors.black),
                        ),
                        subtitle: Text(
                          "\$ ${widget.info.price}",
                          style: TextStyle(
                              fontStyle: FontStyle.normal,
                              fontSize: 14,
                              color: Colors.black),
                        ),
                        trailing: Wrap(
                          spacing: 12,
                          children: [
                            GestureDetector(
                                onTap: () {
                                  setState(() => _isPressed = !_isPressed);
                                },
                                child: Icon(Icons.favorite_sharp,
                                    // color: Colors.redAccent,
                                    color: (isPressed)
                                        ? Colors.red
                                        : Colors.black12)),
        
                            // Icon(
                            //   Icons.add_shopping_cart,
                            //   color: Colors.white,
                            // ),
                          ],
                        ),
    

    Now use the CardWidget to populate the ListView. Just remember to pass in all the values to the widget as shown below.

    ListView.builder(
          itemCount: infoList.length,
          itemBuilder: (BuildContext context, int index) {
            Info info = new Info(
              "${infoList[index].id}",
              "${infoList[index].name}",
              "${infoList[index].image}",
              "${infoList[index].thumb}",
              "${infoList[index].catagory}",
              "${infoList[index].price}",
              "${infoList[index].qty}",
            );
            return CardWidget(info);