使用ConvexBottomBar包遇到两个冲突问题求助
解决ConvexBottomBar与PageView的冲突问题
核心思路
问题根源在于两点:
- PageView的
onPageChanged会在滑动过程中多次触发(比如从0滑到2会依次触发索引1、2),直接调用tap(index)会导致底部导航栏出现中间选中状态 - 需要区分「用户手动滑动PageView」和「点击底部导航跳转」两种场景,只在滑动完成后更新底部导航的选中状态,同时避免点击跳转时的中间状态干扰
解决方案代码
class GameShellViewState extends State<GameShellView> { final PageController _pageController = PageController(initialPage: 1); int _currentIndex = 1; bool _isManualTap = false; // 标记是否为底部导航点击触发的跳转 final _appBarKey = GlobalKey<ConvexAppBarState>(); @override void initState() { super.initState(); _pageController.addListener(_pageListener); } void _pageListener() { // 仅当滚动完全结束时,才更新底部导航选中状态 if (_pageController.position.isScrollingCompleted) { final newIndex = _pageController.page!.round(); if (newIndex != _currentIndex && !_isManualTap) { _appBarKey.currentState!.tap(newIndex); setState(() { _currentIndex = newIndex; }); } _isManualTap = false; // 重置标记 } } void _onTap(int index) { setState(() { _currentIndex = index; _isManualTap = true; // 标记为手动点击跳转 }); _pageController.animateToPage(index, duration: const Duration(milliseconds: 300), curve: Curves.easeOut); } @override void dispose() { _pageController.removeListener(_pageListener); _pageController.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return Scaffold( extendBody: true, body: PageView( controller: _pageController, // 移除原有的onPageChanged,改用controller监听 children: const [ CareerView(), EducationView(), VidaView(), ], ), bottomNavigationBar: ConvexAppBar( key: _appBarKey, elevation: 0, style: TabStyle.reactCircle, items: const [ TabItem(icon: Icons.work, title: 'Career'), TabItem(icon: Icons.school, title: 'Education'), TabItem(icon: Icons.heart_broken, title: 'Vida'), ], initialActiveIndex: 2, onTap: _onTap, backgroundColor: Theme.of(context).colorScheme.surfaceVariant, activeColor: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary, ), ); } }
关键修改点说明
- 添加
_currentIndex状态变量:跟踪当前实际选中的页面索引,避免重复更新底部导航 - 添加
_isManualTap标记:区分用户点击底部导航的跳转行为,此时即使PageView滑动经过中间索引,也不会触发底部导航的状态更新 - 改用PageController监听器:替代原有的
onPageChanged,仅在滚动完全结束时(isScrollingCompleted为true)才更新底部导航的选中状态,确保只处理最终的目标索引 - 清理资源:在
dispose中移除监听器,避免内存泄漏
内容的提问来源于stack exchange,提问作者JAgüero
相关产品推荐
相关产品推荐

