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

Flutter中如何为同一底部导航栏添加多个OnTap事件

解决底部导航栏图标独立跳转页面的问题

问题核心是你当前给所有BtmNavItem传递了同一个press回调,导致点击任何图标都会执行相同的导航逻辑。要实现独立跳转,需要让每个导航项绑定自己的目标页面,下面提供两种可行方案:

方案一:给Menu模型添加页面属性,组件内部处理导航

  1. 首先修改你的Menu模型,新增对应跳转页面的属性:
class Menu {
  final RiveAsset rive;
  // 新增:存储当前导航项对应的目标页面
  final Widget targetPage;

  Menu({required this.rive, required this.targetPage});
}
  1. 修改BtmNavItem组件,移除统一的press参数,直接在onTap中处理导航:
import 'package:flutter/material.dart';
import 'package:rive/rive.dart';

import '../../../model/menu.dart';
import 'animated_bar.dart';

class BtmNavItem extends StatelessWidget {
  const BtmNavItem(
      {super.key,
      required this.navBar,
      required this.riveOnInit,
      required this.selectedNav});

  final Menu navBar;
  final ValueChanged<Artboard> riveOnInit;
  final Menu selectedNav;

  @override
  Widget build(BuildContext context) {
    return GestureDetector(
      onTap: () {
        // 跳转到当前导航项对应的页面
        Navigator.push(
          context,
          MaterialPageRoute(builder: (context) => navBar.targetPage),
        );
      },
      child: Column(
        mainAxisSize: MainAxisSize.min,
        children: [
          AnimatedBar(isActive: selectedNav == navBar),
          SizedBox(
            height: 36,
            width: 36,
            child: Opacity(
              opacity: selectedNav == navBar ? 1 : 0.5,
              child: RiveAnimation.asset(
                navBar.rive.src,
                artboard: navBar.rive.artboard,
                onInit: riveOnInit,
              ),
            ),
          ),
        ],
      ),
    );
  }
}
  1. 在父组件中初始化导航项时,绑定对应的页面:
// 示例:初始化导航列表
final List<Menu> bottomNavItems = [
  Menu(
    rive: RiveAsset(src: "assets/rive/home.riv", artboard: "Home"),
    targetPage: const HomePage(), // 替换成你的首页
  ),
  Menu(
    rive: RiveAsset(src: "assets/rive/profile.riv", artboard: "Profile"),
    targetPage: const ProfilePage(), // 替换成你的个人页面
  ),
  // 其他导航项...
];

方案二:父组件传递独立的回调函数(更灵活)

如果不想修改Menu模型,可以在父组件中为每个BtmNavItem单独传递press回调:

// 父组件中构建导航栏
Row(
  mainAxisAlignment: MainAxisAlignment.spaceAround,
  children: bottomNavItems.map((navItem) {
    return BtmNavItem(
      navBar: navItem,
      riveOnInit: (artboard) { /* 你的Rive初始化逻辑 */ },
      selectedNav: currentSelectedNav, // 当前选中的导航项
      // 每个导航项绑定独立的跳转逻辑
      press: () {
        Navigator.push(
          context,
          MaterialPageRoute(
            builder: (context) {
              // 根据导航项返回对应的页面
              if (navItem.rive.artboard == "Home") {
                return const HomePage();
              } else if (navItem.rive.artboard == "Profile") {
                return const ProfilePage();
              }
              // 默认页面
              return const DefaultPage();
            },
          ),
        );
      },
    );
  }).toList(),
)

关键说明

  • 之前的问题本质是回调复用:所有导航项共享同一个press函数,自然会跳转到同一页面。
  • 如果使用路由名称而非直接传递Widget,可以在MaterialApp中注册路由,然后用Navigator.pushNamed(context, navItem.routeName)实现跳转,适合复杂的路由场景。

内容的提问来源于stack exchange,提问作者محمد امجد

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.25 15:32:56