[FLUTTER]:以编程方式将 CustomNavigator 中的选项卡从 SecondScreen 更改为 FirstScreen

问题描述

我目前正在制作带有底部导航器的应用。我在以编程方式在 SecondScreen 文件中从 SecondScreen 导航到 FirstScreen 时遇到了麻烦。但我不知道该怎么做。因为我无法访问 CustomNavigatorState 类的 CustomNavigator 部分。

我的ma​​in.dart文件

import 'package:Flutter/material.dart';

import './screens/custom_navigator.dart';

void main() async {
  runApp(MyApp());
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
       title: 'App Name',home: Scaffold(
          body: CustomNavigator(),),);
  }
}

我的 custom_navigator.dart 文件,其中包括 CustomNavigator 类和 _CustomNavigatorState 类:

import 'package:Flutter/material.dart';

import './first_second.dart';
import './second_screen.dart';
import './third_screen.dart';

import '../widgets/tab_navigator.dart';

class CustomNavigator extends StatefulWidget {
  @override
  State<StatefulWidget> createState() => _CustomNavigatorState();
}

class _CustomNavigatorState extends State<CustomNavigator> {
  String _currentScreen = FirstScreen.route;
  List<String> _screenKeys = [
    FirstScreen.route,SecondScreen.route,ThirdScreen.route,];
  Map<String,GlobalKey<NavigatorState>> _navigatorKeys = {
    FirstScreen.route: GlobalKey<NavigatorState>(),SecondScreen.route: GlobalKey<NavigatorState>(),ThirdScreen.route: GlobalKey<NavigatorState>(),};
  int _selectedindex = 0;

  void changeTab(String tabItem,int index) {
    _selectedTab(tabItem,index);
  }

  void _selectedTab(String tabItem,int index) {
    if (tabItem == _currentScreen) {
      _navigatorKeys[tabItem].currentState.popUntil((route) => route.isFirst);
    } else {
      setState(() {
        _currentScreen = _screenKeys[index];
        _selectedindex = index;
      });
    }
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
      onWillPop: () async {
        final isFirstRouteInCurrentTab =
            !await _navigatorKeys[_currentScreen].currentState.maybePop();
        if (isFirstRouteInCurrentTab) {
          if (_currentScreen != FirstScreen.route) {
            _selectedTab(FirstScreen.route,1);
            return false;
          }
        }
        return isFirstRouteInCurrentTab;
      },child: Scaffold(
        resizetoAvoidBottomPadding: true,body: Stack(
          children: [
            _buildOffstageNavigator(FirstScreen.route),_buildOffstageNavigator(ScreenScreen.route),_buildOffstageNavigator(ThirdScreen.route),],bottomNavigationBar: BottomNavigationBar(
          onTap: (index) {
            _selectedTab(_screenKeys[index],index);
          },currentIndex: _selectedindex,items: [
            BottomNavigationBarItem(
              label: 'First',BottomNavigationBarItem(
              label: 'Second',BottomNavigationBarItem(
              label: 'Third',);
  }

  Widget _buildOffstageNavigator(String tabItem) {
    return Offstage(
      offstage: _currentScreen != tabItem,child: TabNavigator(
        navigatorKey: _navigatorKeys[tabItem],tabItem: tabItem,);
  }
}

TabNavigator 类,添加屏幕的位置。

import 'package:Flutter/material.dart';

import '../screens/first_screen.dart';
import '../screens/second_screen.dart';
import '../screens/third_screen.dart';

class TabNavigator extends StatelessWidget {
  final GlobalKey<NavigatorState> navigatorKey;
  final String tabItem;

  const TabNavigator({
    Key key,this.navigatorKey,this.tabItem,}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    Widget child;

    if (tabItem == FirstScreen.route) {
      child = FirstScreen();
    } else if (tabItem == SecondScreen.route) {
      child = SecondScreen();
    } else if (tabItem == ThirdScreen.route) {
      child = ThirdScreen();
    }

    return Navigator(
      key: navigatorKey,onGenerateRoute: (routeSettings) {
        return MaterialPageRoute(
          builder: (context) => child,);
      },);
  }
}

我尝试使用 Navigator.pushNavigator.pushNamed 导航,但它在 SecondScreen 内导航而不更改 BottomNavigationTabBars。

Navigator.of(context).push(
   MaterialPageRoute(
     builder: (_) => SecondScreen(),);
Navigator.of(context).pushNamed(SecondScreen.route);

此外,我无法使用 Provider,因为我无权访问 _CustomNavigatorState 类。任何人都可以向我提供有关该问题的任何决定。谢谢。

解决方法

我注意到您有嵌套的 Scaffolds,最好将您的 BottomNavigationBar 移到外部 Scaffold,这样您的应用程序中就只有一个 Scaffold。对于外部 Scaffold 的主体,您将拥有 Stack

关于导航器问题。 Stack 中的应用程序主体,带有三个后台小部件。一次只能看到一个小部件。在每个 Offstage 小部件之间切换时,您实际上并没有导航到它,您要做的就是将您的 _currentScreen 更改为您想要的任何一个。因此,如果您在第一页上并想“推”到第 2 页,那么请使用类似

onPressed: () {
    SetState(() {
        _currentScreen = FirstScreen.route;
    }
}

然后,当您的身体从 setState 重建时,它会将 FirstScreen 设置为在舞台上,并将所有其他屏幕设置为在舞台外。向您展示FirstScreen

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...