如何借助Flutter Bloc Cubit在底部导航栏聊天项添加消息角标?
实现底部导航栏聊天项角标(Flutter Bloc/Cubit方案)
核心思路
通过全局的UnreadMessagesCubit统一管理未读消息总数,新消息到来时更新状态,底部导航栏组件监听该状态变化,动态渲染角标,保证聊天列表与底部导航的未读状态同步。
步骤实现
1. 创建未读消息管理Cubit
import 'package:flutter_bloc/flutter_bloc.dart'; class UnreadMessagesCubit extends Cubit<int> { UnreadMessagesCubit() : super(0); // 新增一条未读消息 void incrementUnread() => emit(state + 1); // 重置未读数(进入聊天页时调用) void resetUnread() => emit(0); // 批量更新未读总数(比如从接口拉取初始数据) void updateUnreadCount(int count) => emit(count); }
2. 在App顶层注入Cubit
确保根组件被BlocProvider包裹,让全局组件都能访问该Cubit:
void main() { runApp( BlocProvider( create: (context) => UnreadMessagesCubit(), child: const MyApp(), ), ); }
3. 底部导航栏监听状态渲染角标
用BlocBuilder监听UnreadMessagesCubit状态,给聊天导航项添加角标(这里用Flutter自带Badge,也可替换第三方Badge库):
int _selectedIndex = 0; final List<Widget> _pages = [/* 对应5个页面的组件 */]; @override Widget build(BuildContext context) { return Scaffold( body: _pages[_selectedIndex], bottomNavigationBar: BlocBuilder<UnreadMessagesCubit, int>( builder: (context, unreadCount) { return BottomNavigationBar( items: [ const BottomNavigationBarItem(icon: Icon(Icons.home), label: '首页'), const BottomNavigationBarItem(icon: Icon(Icons.search), label: '发现'), // 聊天导航项:根据未读数量显示角标 BottomNavigationBarItem( icon: unreadCount > 0 ? Badge( label: Text(unreadCount.toString()), smallSize: 16, child: const Icon(Icons.chat), ) : const Icon(Icons.chat), label: '聊天', ), const BottomNavigationBarItem(icon: Icon(Icons.notifications), label: '通知'), const BottomNavigationBarItem(icon: Icon(Icons.person), label: '我的'), ], currentIndex: _selectedIndex, onTap: (index) { setState(() => _selectedIndex = index); // 切换到聊天页时重置未读数 if (index == 2) { context.read<UnreadMessagesCubit>().resetUnread(); } }, ); }, ), ); }
4. 触发未读状态更新
- 新消息到来时(如WebSocket推送、接口回调),调用Cubit方法更新:
// 示例:收到新消息时触发 void onNewMessageReceived() { context.read<UnreadMessagesCubit>().incrementUnread(); }
- 若从本地存储/接口加载初始未读数据,可在Cubit初始化时处理:
UnreadMessagesCubit() : super(0) { _loadInitialUnreadCount(); } Future<void> _loadInitialUnreadCount() async { // 模拟从本地或接口获取未读总数 int count = await ChatRepository.getTotalUnreadCount(); updateUnreadCount(count); }
注意事项
- 若用第三方Badge组件(如
flutter_badge),需先添加依赖,用法与自带Badge类似 - 多会话场景下,需在Cubit中汇总所有会话的未读数量,保证总数准确
- 可自定义角标样式(大小、颜色、位置等)适配App风格
内容的提问来源于stack exchange,提问作者Mus
相关产品推荐
相关产品推荐

