问题描述
我目前正在制作带有底部导航器的应用。我在以编程方式在 SecondScreen 文件中从 SecondScreen
导航到 FirstScreen
时遇到了麻烦。但我不知道该怎么做。因为我无法访问 CustomNavigatorState
类的 CustomNavigator
部分。
我的main.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.push
和 Navigator.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
。