Flutter实现选中问题添加至指定自定义列表的技术求助
解决方案
核心问题在于你的CreatedList模型未关联问题集合,且CreatedListsNotifier缺少将问题与指定列表绑定的逻辑。以下是完整修正步骤:
1. 重构CreatedList数据结构
确保每个列表包含自身标题和对应的问题集合,并重写比较方法保证列表能被正确识别:
class CreatedList { final String title; final List<Question> questions; CreatedList({required this.title, List<Question>? questions}) : questions = questions ?? []; @override bool operator ==(Object other) => identical(this, other) || other is CreatedList && runtimeType == other.runtimeType && title == other.title; @override int get hashCode => title.hashCode; // 用于复制列表并更新问题集合 CreatedList copyWith({List<Question>? questions}) { return CreatedList( title: title, questions: questions ?? this.questions, ); } }
2. 更新CreatedListsNotifier逻辑
添加管理问题与列表关联的核心方法,保留原有列表增删逻辑:
class CreatedListsNotifier extends StateNotifier<List<CreatedList>> { CreatedListsNotifier() : super([]); // 创建新列表并直接添加当前问题 void createListWithQuestion(CreatedList newList, Question question) { if (!state.contains(newList)) { final updatedList = newList.copyWith(questions: [question]); state = [...state, updatedList]; } } // 给已有列表添加/移除指定问题 void toggleQuestionInList(CreatedList targetList, Question question) { state = state.map((list) { if (list == targetList) { final updatedQuestions = List.of(list.questions); updatedQuestions.contains(question) ? updatedQuestions.remove(question) : updatedQuestions.add(question); return list.copyWith(questions: updatedQuestions); } return list; }).toList(); } // 从所有列表中移除某个问题 void removeQuestionFromAllLists(Question question) { state = state.map((list) { final updatedQuestions = List.of(list.questions)..remove(question); return list.copyWith(questions: updatedQuestions); }).toList(); } // 原有列表创建/删除方法 bool toggleCreatedListsStatus(CreatedList newestList) { final alreadyCreatedList = state.contains(newestList); if (alreadyCreatedList) { state = state.where((L) => L.title != newestList.title).toList(); return false; } else { state = [...state, newestList]; return true; } } void onDismissListItem(CreatedList item) { state = state.where((indexeditem) => indexeditem.title != item.title).toList(); } } final createdListsProvider = StateNotifierProvider<CreatedListsNotifier, List<CreatedList>>((ref) { return CreatedListsNotifier(); });
3. 重构favoriteQuestionsProvider
让它自动计算所有列表中的问题集合,无需单独维护:
final favoriteQuestionsProvider = Provider<List<Question>>((ref) { final createdLists = ref.watch(createdListsProvider); // 合并所有列表的问题并去重 return createdLists.expand((list) => list.questions).toSet().toList(); });
4. 修改主页面逻辑
传递当前问题到弹窗,并处理移除所有列表的逻辑:
@override Widget build(BuildContext context) { List<Question> getNewListofQuestions = List.of(widget.questions); getNewListofQuestions.shuffle(); var currentQuestion = getNewListofQuestions[currentQuestionIndex]; final favoriteQuestions = ref.watch(favoriteQuestionsProvider); final isFavorite = favoriteQuestions.contains(currentQuestion); void openAddNewListOverlay() { if (isFavorite) { ref.read(createdListsProvider.notifier).removeQuestionFromAllLists(currentQuestion); ScaffoldMessenger.of(context).clearSnackBars(); ScaffoldMessenger.of(context).showSnackBar( const SnackBar( duration: Duration(seconds: 1), content: Text('Question removed from all your lists.'), ), ); } else { showModalBottomSheet( shape: const BeveledRectangleBorder( borderRadius: BorderRadius.only( topLeft: Radius.circular(10), topRight: Radius.circular(10), ), ), isScrollControlled: true, useSafeArea: true, context: context, builder: (ctx) => QuestionsOverlayItem( currentQuestion: currentQuestion, onCreateList: (newList) { ref.read(createdListsProvider.notifier).createListWithQuestion(newList, currentQuestion); }, onSelectExistingList: (existingList) { ref.read(createdListsProvider.notifier).toggleQuestionInList(existingList, currentQuestion); }, ), ); } } // 剩余UI代码保持不变... }
5. 调整弹窗组件QuestionsOverlayItem
添加已有列表的展示和选择逻辑(需改为ConsumerWidget或使用Consumer获取Provider):
class QuestionsOverlayItem extends ConsumerWidget { final Question currentQuestion; final Function(CreatedList)? onCreateList; final Function(CreatedList)? onSelectExistingList; const QuestionsOverlayItem({ super.key, required this.currentQuestion, this.onCreateList, this.onSelectExistingList, }); @override Widget build(BuildContext context, WidgetRef ref) { final createdLists = ref.watch(createdListsProvider); return Padding( padding: EdgeInsets.only(bottom: MediaQuery.of(context).viewInsets.bottom), child: Column( mainAxisSize: MainAxisSize.min, children: [ // 新建列表输入框 TextField( decoration: const InputDecoration(labelText: 'New List Title'), onSubmitted: (title) { if (title.isNotEmpty) { onCreateList?.call(CreatedList(title: title)); Navigator.pop(context); } }, ), const SizedBox(height: 16), // 已有列表选择区 const Text('Add to existing lists:'), ...createdLists.map((list) { return ListTile( title: Text(list.title), trailing: Icon( list.questions.contains(currentQuestion) ? Icons.check : null, ), onTap: () { onSelectExistingList?.call(list); Navigator.pop(context); }, ); }), ], ), ); } }
完成以上修改后,即可实现:
- 点击星标,若问题已在列表中则从所有列表移除
- 弹窗中可新建列表并添加当前问题,或选择已有列表添加/移除问题
favoriteQuestionsProvider自动同步所有列表中的问题
内容的提问来源于stack exchange,提问作者yosoybunal
相关产品推荐
相关产品推荐

