图标按钮颜色在离开页面后不会保持为指定的收藏颜色。

huangapple go评论59阅读模式
英文:

iconButton color for favorite function does not stay as designated favorite color after leaving the page

问题

我正在使用Provider创建一个收藏功能,用于将项目添加到收藏页面。以下是我的FavoriteProvider代码。

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

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:firebase_auth/firebase_auth.dart';

import '../model/market_model.dart';

class FavoriteProvider extends ChangeNotifier {
  final List<CryptoItemModel> _favoriteItems = [];
  List<CryptoItemModel> get favoriteItems => _favoriteItems;

  FavoriteProvider() {
    fetchFavorites();
  }

  // 其他方法的代码...

  Future<void> fetchFavorites() async {
    try {
      final user = FirebaseAuth.instance.currentUser;
      if (user == null) {
        print('User is not logged in.');
         return;
      }

      final userEmail = user.email;
      final userRef =
          FirebaseFirestore.instance.collection('userData').doc(userEmail);

      final snapshot = await userRef.collection('favorites').get();
      final favoriteList = snapshot.docs
          .map((doc) => CryptoItemModel.fromMap(doc.data()))
          .toList();

      _favoriteItems.clear();
      _favoriteItems.addAll(favoriteList);
    } catch (e) {
      print('Error retrieving favorites: $e');
    }

    notifyListeners();
  }

  // 其他方法的代码...
}

这是我在不同文件中调用收藏功能的地方。

Consumer<FavoriteProvider>(
  builder: (context, provider, _) {
    return IconButton(
      iconSize: 35,
      onPressed: () {
        Provider.of<FavoriteProvider>(context, listen: false)
            .toggleFavorite(item);
      },
      icon: provider.isExist(item)
          ? const Icon(Icons.star,
              color: Colors.yellow)
          : const Icon(Icons.star_outline,
              color: Colors.grey),
    );
  },
)

这是用于存储收藏项目的页面。

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

import '../body/market_body.dart';
import '../cubit/bottom_navigation_cubit.dart.dart';
import '../provider/watchlist_provider.dart';
import '../widget/bottom_navigation.dart';
import '../widget/market_card.dart';

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

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

class _WatchListState extends State<WatchList> {
  @override
  void initState() {
    super.initState();
    final favoriteProvider =
        Provider.of<FavoriteProvider>(context, listen: false);
    favoriteProvider.fetchFavorites().then((_) {
      if (mounted) {
        setState(() {});
      }
    });
  }

  // 页面的其他部分代码...

  @override
  Widget build(BuildContext context) {
    return BlocProvider<BottomNavigationBarCubit>(
      create: (context) => BottomNavigationBarCubit(3),
      child: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          automaticallyImplyLeading: false,
          backgroundColor: const Color(0xFF0D0D2B),
          title: Image.asset(
            'assets/light_logo.png',
            width: 150.0,
          ),
          centerTitle: true,
        ),
        body: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Padding(
                padding: EdgeInsets.only(top: 18.0, left: 12.0),
                child: Column(
                  children: const [
                    Text(
                      'Watchlist',
                      textAlign: TextAlign.start,
                      style:
                          TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
              // 页面的其他部分代码...
            ],
          ),
        ),
        bottomNavigationBar: const BottomNavigation(),
      ),
    );
  }
}

您描述的问题是,当离开页面并返回时,图标按钮的状态似乎没有保存。这可能是因为在页面重建时,状态未正确初始化。为了解决这个问题,您可以尝试在页面的initState方法中调用favoriteProvider.fetchFavorites(),以确保在构建页面之前加载收藏项目列表。这应该有助于保持图标按钮的正确状态。

请尝试这个建议,看看是否解决了您的问题。如果问题仍然存在,请提供更多详细信息,以便我可以提供更多帮助。

英文:

im creating a favorite function using provider to favorite an item to the favorite page. Here is my FavoriteProvider code.

import &#39;package:flutter/material.dart&#39;;
import &#39;package:provider/provider.dart&#39;;

import &#39;package:cloud_firestore/cloud_firestore.dart&#39;;
import &#39;package:firebase_auth/firebase_auth.dart&#39;;

import &#39;../model/market_model.dart&#39;;

class FavoriteProvider extends ChangeNotifier {
  final List&lt;CryptoItemModel&gt; _favoriteItems = [];
  List&lt;CryptoItemModel&gt; get favoriteItems =&gt; _favoriteItems;

  FavoriteProvider() {
    fetchFavorites();
  }

  Future&lt;void&gt; toggleFavorite(CryptoItemModel item) async {
    final user = FirebaseAuth.instance.currentUser;
    if (user == null) {
      print(&#39;User is not logged in.&#39;);
      return;
    }

    final userEmail = user.email;
    final userRef =
        FirebaseFirestore.instance.collection(&#39;userData&#39;).doc(userEmail);

    try {
      final index =
          _favoriteItems.indexWhere((favItem) =&gt; favItem.name == item.name);
      if (index != -1) {
        _removeFavoriteByIndex(index);
        await userRef.collection(&#39;favorites&#39;).doc(item.name).delete();
      } else {
        _favoriteItems.add(item);
        await userRef.collection(&#39;favorites&#39;).doc(item.name).set(item.toMap());
      }
      notifyListeners();
    } catch (e) {
      print(&#39;Error toggling favorite: $e&#39;);
    }
  }

  Future&lt;void&gt; fetchFavorites() async {
    try {
      final user = FirebaseAuth.instance.currentUser;
      if (user == null) {
        print(&#39;User is not logged in.&#39;);
         return;
      }

      final userEmail = user.email;
      final userRef =
          FirebaseFirestore.instance.collection(&#39;userData&#39;).doc(userEmail);

      final snapshot = await userRef.collection(&#39;favorites&#39;).get();
      final favoriteList = snapshot.docs
          .map((doc) =&gt; CryptoItemModel.fromMap(doc.data()))
          .toList();

      _favoriteItems.clear();
      _favoriteItems.addAll(favoriteList);
    } catch (e) {
      print(&#39;Error retrieving favorites: $e&#39;);
    }

    notifyListeners();
  }

  bool isExist(CryptoItemModel item) {
    final isExist = _favoriteItems.contains(item);
    return isExist;
  }

  void _removeFavoriteByIndex(int index) {
    if (index &gt;= 0 &amp;&amp; index &lt; _favoriteItems.length) {
      _favoriteItems.removeAt(index);
      notifyListeners();
    }
  }

  static FavoriteProvider of(BuildContext context, {bool listen = true}) {
    return Provider.of&lt;FavoriteProvider&gt;(context, listen: listen);
  }
}

and here is where i call the function to favorite inside a different file.

                                Consumer&lt;FavoriteProvider&gt;(
                                  builder: (context, provider, _) {
                                    return IconButton(
                                      iconSize: 35,
                                      onPressed: () {
                                        Provider.of&lt;FavoriteProvider&gt;(context,
                                                listen: false)
                                            .toggleFavorite(item);
                                      },
                                      icon: provider.isExist(item)
                                          ? const Icon(Icons.star,
                                              color: Colors.yellow)
                                          : const Icon(Icons.star_outline,
                                              color: Colors.grey),
                                    );
                                  },

this is the page where the favorite item will be stored.

import &#39;package:flutter/material.dart&#39;;
import &#39;package:flutter_bloc/flutter_bloc.dart&#39;;
import &#39;package:provider/provider.dart&#39;;

import &#39;../body/market_body.dart&#39;;
import &#39;../cubit/bottom_navigation_cubit.dart.dart&#39;;
import &#39;../provider/watchlist_provider.dart&#39;;
import &#39;../widget/bottom_navigation.dart&#39;;
import &#39;../widget/market_card.dart&#39;;

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

  @override
  _WatchListState createState() =&gt; _WatchListState();
}

class _WatchListState extends State&lt;WatchList&gt; {
  @override
  void initState() {
    super.initState();
    final favoriteProvider =
        Provider.of&lt;FavoriteProvider&gt;(context, listen: false);
    favoriteProvider.fetchFavorites().then((_) {
      if (mounted) {
        setState(() {});
      }
    });
  }

  @override
  Widget build(BuildContext context) {
    return BlocProvider&lt;BottomNavigationBarCubit&gt;(
      create: (context) =&gt; BottomNavigationBarCubit(3),
      child: Scaffold(
        backgroundColor: Colors.white,
        appBar: AppBar(
          automaticallyImplyLeading: false,
          backgroundColor: const Color(0xFF0D0D2B),
          title: Image.asset(
            &#39;assets/light_logo.png&#39;,
            width: 150.0,
          ),
          centerTitle: true,
        ),
        body: Padding(
          padding: const EdgeInsets.all(10.0),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              Padding(
                padding: EdgeInsets.only(top: 18.0, left: 12.0),
                child: Column(
                  children: const [
                    Text(
                      &#39;Watchlist&#39;,
                      textAlign: TextAlign.start,
                      style:
                          TextStyle(fontSize: 30, fontWeight: FontWeight.bold),
                    ),
                  ],
                ),
              ),
              Padding(
                padding: EdgeInsets.only(top: 10.0, left: 12.0),
                child: Column(
                  children: const [
                    Text(
                      &#39;View your favorite coins here!&#39;,
                      style: TextStyle(fontSize: 15, color: Color(0xFFBB0163)),
                    ),
                  ],
                ),
              ),
              const SizedBox(
                height: 10,
              ),
              Expanded(
                child: Consumer&lt;FavoriteProvider&gt;(
                  builder: (context, provider, _) {
                    final favoriteItems = provider.favoriteItems;

                    if (favoriteItems.isEmpty) {
                      return const Center(
                        child: Padding(
                          padding: EdgeInsets.all(18.0),
                          child: Text(
                            &quot;Oops.. you have nothing on your watchlist&quot;,
                            style: TextStyle(fontSize: 16),
                          ),
                        ),
                      );
                    }

                    return ListView.builder(
                      itemCount: favoriteItems.length,
                      itemBuilder: (context, index) {
                        final item = favoriteItems[index];
                        return GestureDetector(
                          onTap: () {
                            Navigator.push(
                              context,
                              MaterialPageRoute(
                                builder: (context) =&gt; CryptoDescr(
                                  currency: item,
                                ),
                              ),
                            );
                          },
                          child: MarketCard(
                            name: item.name,
                            symbol: item.symbol,
                            price: item.price,
                            change: item.change,
                            percent: item.percent,
                            imageUrl: item.imageUrl,
                            marketCap: item.marketCap,
                          ),
                        );
                      },
                    );
                  },
                ),
              ),
            ],
          ),
        ),
        bottomNavigationBar: const BottomNavigation(),
      ),
    );
  }
}

i can get the item to be stored inside firebase okay, and when you click on the star iconButton to favorite it, the color will change to yellow as intended. But when i leave the page and come back to it, the iconButton will change back to it previous position as if the item weren't added to the favorite but it was indeed added.

Is there a way that I can fix this problem and if so can someone please help me.

答案1

得分: 0

我终于解决了这个问题!

我面临的问题是因为 isExist 方法使用了 contains 方法,该方法只检查对象的相等性,而不比较项目的属性。

所以我所做的是,我更新了 FavoriteProvider 类中的 isExist 方法,以比较项目的属性,而不是使用 contains 方法。

现在看起来是这样的:

bool isExist(CryptoItemModel item) {
  final isExist = _favoriteItems.any(
    (favItem) => favItem.name == item.name,
  );
  return isExist;
}

现在,无论我何时离开包含该 iconButton 的页面然后返回,iconButton 都会保持为收藏状态!

英文:

I finally fix the problem!

The problem that I'm facing occurs because the isExist method uses the contains method, which checks for object equality only and not comparing the properties of the items.

So what I did is, I update the isExist method in FavoriteProvider class to compare the properties of the items instead of using the contains method.

here how it looks now:

bool isExist(CryptoItemModel item) {
  final isExist = _favoriteItems.any(
    (favItem) =&gt; favItem.name == item.name,
  );
  return isExist;
}

now whenever I leave that page contain the iconButton and then come back, the iconButton will stay as favorite!

huangapple
  • 本文由 发表于 2023年7月12日 22:59:36
  • 转载请务必保留本文链接:https://go.coder-hub.com/76671964.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定