Flutter中如何为同一底部导航栏添加多个OnTap事件
解决底部导航栏图标独立跳转页面的问题
问题核心是你当前给所有BtmNavItem传递了同一个press回调,导致点击任何图标都会执行相同的导航逻辑。要实现独立跳转,需要让每个导航项绑定自己的目标页面,下面提供两种可行方案:
方案一:给Menu模型添加页面属性,组件内部处理导航
- 首先修改你的
Menu模型,新增对应跳转页面的属性:
class Menu { final RiveAsset rive; // 新增:存储当前导航项对应的目标页面 final Widget targetPage; Menu({required this.rive, required this.targetPage}); }
- 修改
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, ), ), ), ], ), ); } }
- 在父组件中初始化导航项时,绑定对应的页面:
// 示例:初始化导航列表 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,提问作者محمد امجد
相关产品推荐
相关产品推荐

