Flutter NavBar - 单击后不返回主页

问题描述 投票:0回答:1

我在 Flutter 中写了一个 NavBar:

class SfxNavBar extends StatefulWidget {
  const SfxNavBar({super.key});

  @override
  SfxNavBarState createState() => SfxNavBarState();
}

class SfxNavBarState extends State<SfxNavBar> {
  int _selectedIndex = 0;
  
  final List<GlobalKey<NavigatorState>> _navigatorKeys = [
    GlobalKey<NavigatorState>(), // Home
    GlobalKey<NavigatorState>(), // Info
    GlobalKey<NavigatorState>(), // Events
    GlobalKey<NavigatorState>(), // Pray
  ];

  void _onItemTapped(int index) {
    if (index == _selectedIndex) {
      _navigatorKeys[index].currentState?.popUntil((route) => route.isFirst);
    } else {
      setState(() {
        _selectedIndex = index;
      });
    }
  }

  Future<bool> _onWillPop() async {
    final isFirstRouteInCurrentTab =
        !await _navigatorKeys[_selectedIndex].currentState!.maybePop();
    if (isFirstRouteInCurrentTab) {
      return true;
    } else {
      return false;
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: _onWillPop,
      child: Scaffold(
        body: IndexedStack(
          index: _selectedIndex,
          children: [
            _buildNavigator(0, const HomePage()),  // HomePage
            _buildNavigator(1, const InfoPage()),  // InfoPage
            _buildNavigator(2, const EventsPage()),  // EventsPage
            _buildNavigator(3, const PrayerPage()),  // PrayerPage
          ],
        ),
        bottomNavigationBar: BottomNavigationBar(
          currentIndex: _selectedIndex,
          onTap: _onItemTapped,
          items: const [
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.home),
              label: 'Home',
            ),
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.info),
              label: 'Info',
            ),
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.calendar),
              label: 'Events',
            ),
            BottomNavigationBarItem(
              icon: Icon(CupertinoIcons.hand_raised),
              label: 'Pray',
            ),
          ],
          selectedItemColor: Colors.green,
          unselectedItemColor: Colors.grey,
        ),
      ),
    );
  }

  // Create the Navigator for each tab
  Widget _buildNavigator(int index, Widget child) {
    return Navigator(
      key: _navigatorKeys[index],
      onGenerateRoute: (RouteSettings settings) {
        return MaterialPageRoute(
          builder: (context) => child,
        );
      },
    );
  }
}

我已将主页抽象为

HomeView
HomeContent
HomePage

首页内容:

class HomeContent {
  HomeContent();
}

主页:

class HomePage extends StatelessWidget {
  const HomePage({super.key});

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: const SfxAppBar(
        title: 'Home',
        nextPage: HomePage(),
      ),
      body: BlocBuilder<AppCubit, AppState>(
        builder: (context, state) {
          if (state is AppLoading) {
            return const Center(child: CircularProgressIndicator());
          } else if (state is AppLoaded) {
            return DataPage(
                pageTitle: 'HomePage',
                buildContent: (context, state) {
                  final homeContent = HomeContent();
                  return HomeView(
                    content: homeContent,
                  );
                });
          } else if (state is AppError) {
            return Center(child: Text('Error: ${state.message}'));
          } else {
            return const Center(child: Text('Welcome to the App!'));
          }
        },
      ),
    );
  }
}

主页视图:

class HomeView extends StatelessWidget {
  final HomeContent content;

  const HomeView({super.key, required this.content});

  @override
  Widget build(BuildContext context) {
    return GridView.count(
      padding: const EdgeInsets.all(16.0),
      crossAxisCount: 2,
      crossAxisSpacing: 10.0,
      mainAxisSpacing: 10.0,
      children: [
        _buildGridIcon(context, Icons.notifications, 'Notifications', () {

          // controller.jumpToTab(1); // Navigate to Notifications tab
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const NotificationsPage()),
          );
        }),
        _buildGridIcon(context, Icons.event, 'Events', () { 
          // controller.jumpToTab(2);
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const EventsPage()),
          );
        }),
        _buildGridIcon(context, Icons.church, 'Mass Schedule', () {
          
          // controller.jumpToTab(3);
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const MassSchedulePage()),
          );
        }),
        _buildGridIcon(context, Icons.volunteer_activism, 'Offertory', () {
          
          // controller.jumpToTab(2);
          Navigator.push(
            context,
            MaterialPageRoute(builder: (context) => const EventsPage()),
          );
        })
        // Add more icons for different pages as needed
      ],
    );
  }

  Widget _buildGridIcon(
      BuildContext context, IconData icon, String label, VoidCallback onTap) {
    return GestureDetector(
      onTap: onTap,
      child: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        children: [
          Icon(icon, size: 50),
          const SizedBox(height: 10),
          Text(label, style: Theme.of(context).textTheme.displaySmall),
        ],
      ),
    );
  }
}

现在的问题是,当我单击 HomeView 中的任何图标时,它会转到另一个页面(例如

NotificationsPage
)。如果我单击导航栏上的
Home
,然后再次单击
Home
,它不会立即返回主页 - 它返回到通知页面,然后我必须再次单击
Home
才能恢复到主页。

我可以做什么来解决这个问题?

flutter flutter-navigation flutter-material
1个回答
0
投票

您可以通过重置当前选项卡的导航器来优化导航逻辑,以确保点击同一选项卡导航到第一页。修改 _onItemTapped 中的 Navigator 逻辑并确保正确重置 Navigator 堆栈:

void _onItemTapped(int index) {
  if (index == _selectedIndex) {
    // Ensure the tab's navigation stack is reset to the root
    _navigatorKeys[index].currentState?.popUntil((route) => route.isFirst);
  } else {
    // Set the selected index to the new tab
    setState(() {
      _selectedIndex = index;
    });
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.