Badriya Haddad
Badriya Haddad

Reputation: 21

Problem in Provider with favorite list - icon changing color in Flutter

I am using a Provider with Favorite list. so the idea is a Listview contains data fetched from Json, each one of them is in Listile has title whish has the main data (string) and and leading that has id of the string and trailing that supposed to has the favorite icon that changes color to red when it taps, but that turns out to be an issue because when I tab on only one all of them changes too but for short of amount of time and the color dispersed, so this is issue number one issue number two is with Provider !! as shown below, when I tab an icon supposed when I tap on the list icon it shows the screen that displayed the favorite list but it won't, instead it shows (Instance of 'Food') but according to the items I tabbed so this is the Home Screen code :

import 'package:flutter/material.dart';
import 'package:flutter/src/widgets/container.dart';
import 'package:flutter/src/widgets/framework.dart';
import 'package:google_fonts/google_fonts.dart';
import 'package:note/Designs/Favorite_List.dart';
import 'package:note/Models/Favorite_List_Provider.dart';
import 'package:note/Models/Food_Models.dart';
import 'package:provider/provider.dart';

import '../Services/Fetch_Data.dart';
import 'Details_DesignOfDesignOne.dart';

class DesignOne extends StatefulWidget {
  const DesignOne({super.key, required this.Image, required this.Desc});
  final String Image;
  final String Desc;
  @override
  State<DesignOne> createState() => _DesignOneState();
}

class _DesignOneState extends State<DesignOne> {
  late Future<Food> futureFood;
  @override
  void initState() {
    super.initState();
    futureFood = fetchData(widget.Image, widget.Desc);
  }

  @override
  Widget build(BuildContext context) {
    bool ischecked = false;
    final provider = favorite.of(context);
    return Scaffold(
      backgroundColor: Colors.grey.shade200,
      appBar: AppBar(
        title: Text('Design one'),
        actions: [
          Padding(
            padding: const EdgeInsets.all(8.0),
            child: InkWell(
              onTap: () {
                Navigator.push(
                  context,
                  MaterialPageRoute(
                    builder: (context) => FavoriteScreen(Desc: '', Image: ''),
                  ),
                );
              },
              child: Icon(
                Icons.list,
                size: 30,
              ),
            ),
          )
        ],
      ),
      body: Consumer<favorite>(
          builder: (BuildContext context, favorite value, child) {
        return Center(
          child: FutureBuilder<Food>(
            future: fetchData(widget.Image, widget.Desc),
            builder: (context, snapshot) {
              if (snapshot.hasData) {
                return ListView.builder(
                    shrinkWrap: true,
                    itemCount: snapshot.data!.categories.length,
                    itemBuilder: (contxt, index) {
                      final fav = snapshot.data!;
                      return InkWell(
                        onTap: () {
                          Navigator.push(
                            context,
                            MaterialPageRoute(
                              builder: (context) => DetailsDo(
                                Desc: snapshot.data!.categories[index]
                                    .strCategoryDescription,
                                Image: snapshot
                                    .data!.categories[index].strCategoryThumb,
                              ),
                            ),
                          );
                        },
                        child: Card(
                          elevation: 2,
                          shape: RoundedRectangleBorder(
                            side: BorderSide(color: Colors.white70, width: 1),
                            borderRadius: BorderRadius.circular(50),
                          ),
                          child: ListTile(
                            title: Text(
                              snapshot.data!.categories[index].strCategory
                                  .toString(),
                              style: GoogleFonts.montserrat(
                                fontSize: 20,
                                fontWeight: FontWeight.w600,
                                fontStyle: FontStyle.italic,
                              ),
                            ),
                            leading: CircleAvatar(
                              backgroundColor:
                                  Color.fromARGB(213, 255, 251, 251),
                              child: Text(
                                snapshot.data!.categories[index].idCategory
                                    .toString(),
                                style: GoogleFonts.montserrat(
                                    fontSize: 20,
                                    fontWeight: FontWeight.w600,
                                    fontStyle: FontStyle.italic,
                                    color: Color.fromARGB(255, 148, 148, 135)),
                              ),
                            ),
                            trailing: IconButton(
                              icon: (provider.isExist(fav))
                                  ? const Icon(Icons.favorite,
                                      color: Colors.red)
                                  : const Icon(Icons.favorite_border),
                              onPressed: () {
                                provider.toggleFavorite(fav);
                              },
                            ),
                          ),
                        ),
                      );
                    });
              } else if (snapshot.hasError) {
                return Text('${snapshot.error}');
              }
              return const CircularProgressIndicator();
            },
          ),
        );
      }),
    );
  }
}

and this is the favorite list screen that supposed to display the favorite items :

import 'dart:ui';

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/widgets.dart';
import 'package:note/Models/Favorite_List_Provider.dart';
import 'package:provider/provider.dart';

import '../Models/Food_Models.dart';
import '../Services/Fetch_Data.dart';

class FavoriteScreen extends StatefulWidget {
  const FavoriteScreen({super.key, required this.Image, required this.Desc});
  final String Image;
  final String Desc;

  @override
  State<FavoriteScreen> createState() => _FavoriteScreenState();
}

class _FavoriteScreenState extends State<FavoriteScreen> {
  @override
  Widget build(BuildContext context) {
    final provider = favorite.of(context);
    final favr = provider.favoriteList;
    return Scaffold(
        appBar: AppBar(
          title: Text("Favorites"),
          centerTitle: true,
        ),
        body: Consumer<favorite>(
          builder: (context, favorite value, child) {
            return FutureBuilder<Food>(
                future: fetchData(widget.Image, widget.Desc),
                builder: (context, snapshot) {
                  if (snapshot.hasData) {
                    return ListView.builder(
                        shrinkWrap: true,
                        itemCount: favr.length,
                        itemBuilder: (context, index) {
                          final fav = favr;
                          return ListView(shrinkWrap: true, children: [
                            ListTile(
                              title: Text(fav[index].toString()),
                            ),
                          ]);
                        });
                  }
                  return const CircularProgressIndicator();
                });
          },
        ));
  }
}

and that is the Provider :

import 'Food_Models.dart';
import 'package:flutter/material.dart';
import 'package:provider/provider.dart';

class favorite extends ChangeNotifier {
  List<Food> _favoriteList = [];
  List<Food> get favoriteList => _favoriteList;

  void toggleFavorite(Food fav) {
    final isExist = _favoriteList.contains(fav);
    if (isExist) {
      _favoriteList.remove(fav);
    } else {
      _favoriteList.add(fav);
    }
    notifyListeners();
  }

  bool isExist(Food fav) {
    final isExist = _favoriteList.contains(fav);
    return isExist;
  }

  void clearFavorite() {
    _favoriteList = [];
    notifyListeners();
  }

  static favorite of(
    BuildContext context, {
    bool listen = true,
  }) {
    return Provider.of<favorite>(
      context,
      listen: listen,
    );
  }
}

so this is what it shows to me : the problem

Upvotes: 0

Views: 326

Answers (1)

pmatatias
pmatatias

Reputation: 4444

  • ISSUE 1: you should add 1 category not all category
final fav = snapshot.data!; // in this line, fav is ALL FOOD 
  return InkWell(
  ....

you declare fav is all the FOOD category. but in your Card you add:

snapshot.data!.categories[index] // this line: only 1 food category

solution: change fav into 1 category:

final fav = snapshot.data!.categories[index];

and in your list should be:

List<Your_favorite_category> _yourfavoriteCategoryList = [];
List<Your_favorite_category> get yourfavoriteCategoryList=> _favoriteList;


  void toggleFavorite(YourFoodCategory fav) {
    final isExist = yourfavoriteCategoryList.contains(fav);
    if (isExist) {
      yourfavoriteCategoryList.remove(fav);
    } else {
      yourfavoriteCategoryList.add(fav);
    }
    notifyListeners();
  }
  • ISSUE 2: you are Print an Object, thats why its display Instance of <Food>
Text(fav[index].toString()) // this is print an object of Food

Solution: in your favorite list, it should be a list of Category. not display the Food Object

Text(fav.your_categories_object[index].toString()) // this is print your category

Upvotes: 0

Related Questions