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

使用ConvexBottomBar包遇到两个冲突问题求助

解决ConvexBottomBar与PageView的冲突问题

核心思路

问题根源在于两点:

  1. PageView的onPageChanged会在滑动过程中多次触发(比如从0滑到2会依次触发索引1、2),直接调用tap(index)会导致底部导航栏出现中间选中状态
  2. 需要区分「用户手动滑动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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.29 20:57:45