我有一个navigation_bar.dart
文件,该文件可以处理我的应用程序中的新页面更改。在其中,我使用bottomNavigationBar
根据当前选择的选项卡来构建四个不同的页面,如下所示:
class NavigationBar extends StatefulWidget {
@override
_NavigationBarState createState() => _NavigationBarState();
}
class _NavigationBarState extends State<NavigationBar> {
int _selectedIndex = 0;
final List<Widget> _pageOptions = <Widget>[
Page1(),
Page2(),
Page3(),
Page4(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
});
}
@override
Widget build(BuildContext context) {
String userID =
Provider.of<FirebaseUser>(context, listen: false) != null ? Provider.of<FirebaseUser>(context).uid : 'null';
return MultiProvider(
providers: [StreamProvider<MyUser>.value(value: DatabaseService().streamUser(userID))],
child: Scaffold(
body: IndexedStack(
children: _pageOptions,
index: _selectedIndex,
),
bottomNavigationBar: Theme(
data: Theme.of(context).copyWith(
canvasColor: Color(0xff271037).withOpacity(0.90),
splashColor: Colors.transparent,
),
child: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
unselectedItemColor: Colors.white,
selectedItemColor: Color(0xff3ADEA7),
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Container(),
title: Icon(FontAwesomeIcons.fire, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: Icon(Icons.fastfood, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: Icon(Icons.directions_bike, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: Icon(Icons.person, color: Colors.white),
)
],
),
),
),
);
}
}
现在,在该页面的另一个Page3.dart
文件中,弹出一个警告对话框,单击该对话框时,我希望它导航到Page4()。
Future<void> _showMissingDataDialog(String data) async {
return showDialog<void>(
context: context,
barrierDismissible: false,
builder: (BuildContext context) {
return AlertDialog(
title: Text('You have not set your $data yet.'),
actions: <Widget>[
FlatButton(
splashColor: Colors.transparent,
highlightColor: Colors.grey[200],
textColor: Colors.black,
child: const Text('Cancel'),
onPressed: () => Navigator.of(context).pop(),
),
FlatButton(
splashColor: Colors.transparent,
highlightColor: Colors.grey[200],
textColor: Colors.black,
child: Text('Set $data', style: TextStyle(fontWeight: FontWeight.bold)),
onPressed: () {
Navigator.of(context).pop();
// TODO: Redirect to page4() here as if it was tapped on the BottomNavigationBar
})
],
);
},
);
}
我如何拥有它,以便单击“设置$ data”按钮将路由到Page4()?我希望这样做,以便bottomNavigationBar
对此做出反应,就像您点击实际的第四个BottomNavigationBarItem
项一样。
答案 0 :(得分:0)
我能够通过使用IndexedStack
并创建一个Provider
类来解决此问题,该类具有从任何其他类更改_currentpage
的值的功能。
class NavigationBar extends StatefulWidget {
@override
_NavigationBarState createState() => _NavigationBarState();
}
class _NavigationBarState extends State<NavigationBar> {
int _selectedIndex = 0;
final List<Widget> _pageOptions = <Widget>[
Page1(),
Page2(),
Page3(),
Page4(),
];
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
Provider.of<NavBarProvider>(context).currentPage = index;
});
}
@override
Widget build(BuildContext context) {
String userID =
Provider.of<FirebaseUser>(context, listen: false) != null ? Provider.of<FirebaseUser>(context).uid : 'null';
return MultiProvider(
providers: [StreamProvider<MyUser>.value(value: DatabaseService().streamUser(userID))],
child: Scaffold(
body: IndexedStack(
children: _pageOptions,
index: Provider.of<NavBarProvider>(context).currentPage,
),
bottomNavigationBar: BottomNavBar(),
),
);
}
}
class BottomNavBar extends StatefulWidget {
BottomNavBar({Key key}) : super(key: key);
_BottomNavBarState createState() => _BottomNavBarState();
}
class _BottomNavBarState extends State<BottomNavBar> {
int _selectedIndex = 0;
@override
void initState() {
_selectedIndex = Provider.of<NavBarProvider>(context, listen: false).currentPage;
super.initState();
}
void _onItemTapped(int index) {
setState(() {
_selectedIndex = index;
Provider.of<NavBarProvider>(context, listen: false).currentPage = index;
});
}
@override
Widget build(BuildContext context) {
return Theme(
data: Theme.of(context).copyWith(
canvasColor: const Color(0xff271037),
splashColor: Colors.transparent,
),
child: BottomNavigationBar(
currentIndex: _selectedIndex,
onTap: _onItemTapped,
unselectedItemColor: Colors.white,
selectedItemColor: const Color(0xff3ADEA7),
type: BottomNavigationBarType.fixed,
items: <BottomNavigationBarItem>[
BottomNavigationBarItem(
icon: Container(),
title: const Icon(FontAwesomeIcons.fire, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: const Icon(Icons.fastfood, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: const Icon(Icons.directions_bike, color: Colors.white),
),
BottomNavigationBarItem(
icon: Container(),
title: const Icon(Icons.person, color: Colors.white),
)
],
),
);
}
}
这是Provider类:
import 'package:flutter/foundation.dart';
class NavBarProvider extends ChangeNotifier {
int _currentPage = 0;
set currentPage(int pageInt) {
_currentPage = pageInt;
notifyListeners();
}
int get currentPage => _currentPage;
}
然后可以通过导入提供程序类并按如下方式更改页面来更改页面:
Provider.of<NavBarProvider>(context).currentpage = 3;
不幸的是,这并不完美,因为它没有为onTapped
模拟BottomNavigationBarItem
。通常,当您单击具有我所拥有代码的图标时,该图标会产生动画效果,使其尺寸增大,而使用此解决方案时不会发生这种情况。只会更改加载的页面。
答案 1 :(得分:0)
为导航栏提供全局密钥。我在主Dart文件的所有小部件之外声明了这一点。
GlobalKey navBarGlobalKey = GlobalKey(debugLabel: 'bottomAppBar');
bottomNavigationBar: BottomNavigationBar(
key: navBarGlobalKey,
onTap: _onItemTapped,
currentIndex: _selectedIndex,
type: BottomNavigationBarType.fixed,
items: [ ... ]
然后使用全局键在按钮的onPressed方法中调用onTap方法。您必须先将另一个dart文件导入此页面,然后才能使用全局密钥。
final BottomNavigationBar navigationBar = navBarGlobalKey.currentWidget;
initialIndex = 0;
navigationBar.onTap(3); //Starts at index 0, so passing in 3 should do the trick.