You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter新手求助:实现圣训收藏页添加功能

Flutter圣训收藏功能实现方案

问题背景

我是Flutter新手,正在开发一个包含圣训(Hadith)列表的项目,每条圣训配有「收藏」按钮,希望点击按钮将对应圣训添加到「收藏页」。目前已完成列表和按钮搭建,但收藏逻辑无效,点击后没有效果。


核心问题分析

  1. 收藏列表未全局共享:你之前的收藏操作函数没有绑定全局实例,导致不同页面的收藏列表互不关联
  2. Hadith类未重写相等判断:contains和remove方法无法识别相同编号的圣训
  3. 收藏状态未同步初始化:进入页面时未读取已有收藏状态,导致按钮显示错误
  4. 导航跳转错误:底部导航的收藏按钮错误跳转到了IndexPage而非收藏页

分步解决方案

1. 重构收藏管理与数据类

在hadith_data.dart中修改,实现全局单例的收藏管理,并修正Hadith类的相等判断:

class Hadith {
  final int hadithNumber;
  final String hadith;
  final String translation;

  Hadith({
    required this.hadithNumber,
    required this.hadith,
    required this.translation,
  });

  // 重写相等判断,确保通过编号识别相同圣训
  @override
  bool operator ==(Object other) =>
      identical(this, other) ||
      other is Hadith &&
          runtimeType == other.runtimeType &&
          hadithNumber == other.hadithNumber;

  @override
  int get hashCode => hadithNumber.hashCode;
}

// 全局单例收藏管理器
class FavoriteHadith {
  static final FavoriteHadith _instance = FavoriteHadith._internal();
  List<Hadith> favoriteHadithList = [];

  factory FavoriteHadith() => _instance;
  FavoriteHadith._internal();

  // 添加收藏
  void addFavorite(Hadith hadith) {
    if (!favoriteHadithList.contains(hadith)) {
      favoriteHadithList.add(hadith);
    }
  }

  // 移除收藏
  void removeFavorite(Hadith hadith) {
    favoriteHadithList.remove(hadith);
  }

  // 判断是否已收藏
  bool isFavorite(Hadith hadith) {
    return favoriteHadithList.contains(hadith);
  }
}

// 全局圣训列表
List<Hadith> hadithList = [
  Hadith(
    hadithNumber: 1,
    hadith: 'hadith 1',
    translation: 'Translation of Hadith 1'
  ),
  // 其他圣训...
];

2. 修正HadithPage的收藏逻辑

修改HadithPage的状态管理,初始化时同步收藏状态,并绑定全局收藏管理器:

class _HadithPageState extends State<HadithPage> {
  late bool isFavorite;
  final FavoriteHadith _favoriteManager = FavoriteHadith();

  @override
  void initState() {
    super.initState();
    // 初始化时读取当前圣训的收藏状态
    isFavorite = _favoriteManager.isFavorite(hadithList[widget.index]);
  }

  @override
  Widget build(BuildContext context) {
    bool isEndOfList = widget.index >= hadithList.length - 1;

    return Scaffold(
      backgroundColor: const Color(0xFFF5E6CA),
      appBar: AppBar(
        title: Text('Hadith ${widget.index + 1}'),
        backgroundColor: const Color(0xFF8B5C3E),
      ),
      body: Column(
        children: [
          Expanded(
            child: ListView(
              children: [
                Column(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: [
                    Text(
                      hadithList[widget.index].hadith,
                      style: const TextStyle(fontSize: 18),
                      textAlign: TextAlign.right,
                    ),
                    const SizedBox(height: 20),
                    Text(
                      hadithList[widget.index].translation,
                      style: const TextStyle(fontSize: 16, fontStyle: FontStyle.italic),
                      textAlign: TextAlign.left,
                    ),
                    IconButton(
                      icon: Icon(
                        isFavorite ? Icons.favorite : Icons.favorite_border,
                        color: isFavorite ? Colors.red : null,
                      ),
                      onPressed: () {
                        setState(() {
                          isFavorite = !isFavorite;
                          if (isFavorite) {
                            _favoriteManager.addFavorite(hadithList[widget.index]);
                          } else {
                            _favoriteManager.removeFavorite(hadithList[widget.index]);
                          }
                        });
                      },
                    ),
                  ],
                ),
              ],
            ),
          ),
          // 前后按钮逻辑保持不变...
        ],
      ),
      bottomNavigationBar: Theme(
        data: Theme.of(context).copyWith(
          canvasColor: const Color(0xFF8B5C3E),
          primaryColor: Colors.black,
          unselectedWidgetColor: Colors.grey,
        ),
        child: BottomNavigationBar(
          items: const <BottomNavigationBarItem>[
            BottomNavigationBarItem(icon: Icon(Icons.home), label: 'Home'),
            BottomNavigationBarItem(icon: Icon(Icons.favorite), label: 'Favorites'),
            BottomNavigationBarItem(icon: Icon(Icons.library_books), label: 'Index'),
            BottomNavigationBarItem(icon: Icon(Icons.settings), label: 'Settings'),
          ],
          onTap: (index) {
            if (index == 1) {
              // 修正跳转至收藏页
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const FavoritesPage()),
              );
            } else if (index == 2) {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const IndexPage()),
              );
            } else if (index == 3) {
              Navigator.push(
                context,
                MaterialPageRoute(builder: (context) => const SettingsPage()),
              );
            }
          },
        ),
      ),
    );
  }
}

3. 实现收藏页面(FavoritesPage)

新建favorites_page.dart,展示收藏的圣训列表并支持移除:

import 'package:flutter/material.dart';
import 'hadith_data.dart';
import 'hadith_page.dart';

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

  @override
  State<FavoritesPage> createState() => _FavoritesPageState();
}

class _FavoritesPageState extends State<FavoritesPage> {
  final FavoriteHadith _favoriteManager = FavoriteHadith();

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: const Color(0xFFF5E6CA),
      appBar: AppBar(
        title: const Text('收藏的圣训'),
        backgroundColor: const Color(0xFF8B5C3E),
      ),
      body: _favoriteManager.favoriteHadithList.isEmpty
          ? const Center(child: Text('暂无收藏的圣训'))
          : ListView.builder(
              itemCount: _favoriteManager.favoriteHadithList.length,
              itemBuilder: (context, index) {
                final hadith = _favoriteManager.favoriteHadithList[index];
                return ListTile(
                  title: Text(
                    hadith.hadith,
                    style: const TextStyle(fontSize: 16),
                    textAlign: TextAlign.right,
                  ),
                  subtitle: Padding(
                    padding: const EdgeInsets.only(top: 8.0),
                    child: Text(
                      hadith.translation,
                      style: const TextStyle(fontSize: 14, fontStyle: FontStyle.italic),
                      textAlign: TextAlign.left,
                    ),
                  ),
                  onTap: () {
                    // 跳转到对应圣训详情页
                    Navigator.push(
                      context,
                      MaterialPageRoute(
                        builder: (context) => HadithPage(
                          index: hadithList.indexWhere((h) => h.hadithNumber == hadith.hadithNumber),
                        ),
                      ),
                    );
                  },
                  trailing: IconButton(
                    icon: const Icon(Icons.favorite, color: Colors.red),
                    onPressed: () {
                      setState(() {
                        _favoriteManager.removeFavorite(hadith);
                      });
                    },
                  ),
                );
              },
            ),
    );
  }
}

内容的提问来源于stack exchange,提问作者mtamuri

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.01 12:50:58