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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 16:43:12