Flutter中点击底部导航栏中心按钮切换首页Widget的实现
问题描述
我在HomeScreen组件的body属性中配置了MapPage()和BottomNavBar()组件,期望点击BottomNavBar()中心浮动按钮里的“Nearby Mechanics”选项时,将body的MapPage()切换为NearbyMechanics()。
尝试过用bool类型变量showMechanics,点击按钮后设为true来切换组件,但变量定义在不同类中,无法实现需求。
现有代码
HomeScreen类代码
class _HomeScreenState extends State<HomeScreen> { @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: const MapPage(), bottomNavigationBar: const BottomNavBar(), )); } }
BottomNavBar类代码
class _BottomNavBarState extends State<BottomNavBar> { var currentIndex = 0; bool? centerModelOpen; @override Widget build(BuildContext context) { return AnimatedBottomNavigationBar( bottomBarCenterModel: BottomBarCenterModel( centerBackgroundColor: kButton, centerIcon: const FloatingCenterButton( child: Icon( Icons.car_crash_rounded, color: AppColors.white, size: 32, ), ), centerIconChild: [ FloatingCenterButtonChild( child: Column( children: const [ Icon( Icons.build, color: AppColors.white, ), Text( "Nearby Mechanics", textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 6.5), ), ], ), onTap: () { //Apply logic of showNearbyMechanics }, ), FloatingCenterButtonChild( child: Column( children: const [ Icon( Icons.local_hotel_rounded, color: AppColors.white, ), Text( "Nearby Hotels", textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 6.5), ), ], ), onTap: () {}, ), FloatingCenterButtonChild( child: Column( children: const [ Icon( Icons.local_gas_station_rounded, color: AppColors.white, ), Text( "Nearby Pumps", textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 6.5), ), ], ), onTap: () {}, ), ], ), ); } }
解决方案
通过子组件向父组件传递回调函数的方式实现页面切换,这是父子组件状态同步最直接的方案:
步骤1:给BottomNavBar添加回调参数
修改BottomNavBar的外部类,新增一个回调函数参数,用来接收父组件的页面切换逻辑:
class BottomNavBar extends StatefulWidget { // 新增回调参数,用于通知父组件切换到Mechanics页面 final VoidCallback? onNearbyMechanicsTap; const BottomNavBar({Key? key, this.onNearbyMechanicsTap}) : super(key: key); @override _BottomNavBarState createState() => _BottomNavBarState(); }
步骤2:绑定按钮的点击事件
在“Nearby Mechanics”按钮的onTap中调用父组件传进来的回调:
// 在_BottomNavBarState的build方法中修改对应按钮 FloatingCenterButtonChild( child: Column( children: const [ Icon( Icons.build, color: AppColors.white, ), Text( "Nearby Mechanics", textAlign: TextAlign.center, style: TextStyle(color: Colors.white, fontSize: 6.5), ), ], ), onTap: () { // 触发父组件的回调 widget.onNearbyMechanicsTap?.call(); }, ),
步骤3:在HomeScreen中维护页面状态
在_HomeScreenState中定义变量控制当前显示的页面,并在回调中更新状态:
class _HomeScreenState extends State<HomeScreen> { // 控制当前显示的页面,初始为MapPage Widget _currentPage = const MapPage(); @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: _currentPage, bottomNavigationBar: BottomNavBar( // 传递页面切换的回调逻辑 onNearbyMechanicsTap: () { setState(() { _currentPage = const NearbyMechanics(); }); }, ), )); } }
扩展:支持多页面切换
如果后续需要切换回MapPage或其他页面,可以用枚举管理页面状态,扩展性更强:
// 定义页面类型枚举 enum PageType { map, mechanics, hotels, pumps } class _HomeScreenState extends State<HomeScreen> { PageType _currentPageType = PageType.map; // 根据当前枚举值返回对应页面 Widget _getCurrentPage() { switch(_currentPageType) { case PageType.map: return const MapPage(); case PageType.mechanics: return const NearbyMechanics(); case PageType.hotels: return const NearbyHotels(); case PageType.pumps: return const NearbyPumps(); default: return const MapPage(); } } @override Widget build(BuildContext context) { return MaterialApp( home: Scaffold( body: _getCurrentPage(), bottomNavigationBar: BottomNavBar( onNearbyMechanicsTap: () { setState(() { _currentPageType = PageType.mechanics; }); }, // 可以继续添加其他按钮的回调 onNearbyHotelsTap: () { setState(() { _currentPageType = PageType.hotels; }); }, ), )); } }
内容的提问来源于stack exchange,提问作者HassamJaved
相关产品推荐
相关产品推荐

