Flutter - 持久底部导航栏 - 如何不在某些页面上显示?
Flutter - Persisting BottomNavigationBar - how not to show on some pages?
我的实现:
main.dart: - 它构建了多脚手架(底部导航栏正在 UI 树上方的所有屏幕上创建)
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: "WP-seven",
builder: (context, child) {
return Scaffold(
bottomNavigationBar: NavyBottomBar(navigator: (child.key as GlobalKey<NavigatorState>)),
body: child,
);
},
home: NewsList(0),
));
NavyBottomBar.dart:为导航栏小部件分隔 class。
这里我们有一个全局导航键,用于 main.dart 以连接到每个 child 的导航器(child 是每个屏幕小部件。)
final GlobalKey<NavigatorState> navigator;
所以还有一个打开页面的逻辑,但是上面的代码足以在每个屏幕上显示 bottomNavigationBar 并能够导航。
问题是我不需要在每个屏幕上都有这个底部导航,应该有办法在某些屏幕上关闭导航栏。
可能有不同的方法来实现这个结果..?
对此最简单的回答是,您应该只在每个单独的页面上构建底部导航栏。导航栏本身可以放入它自己的 Stateless 或 StatefulWidget 中,这样您就不必每次都完全指定它。如果你想让它看起来像是在页面之间持续存在,你可以使用 flutter 的 Hero 功能来做到这一点。
如果这不是您愿意做的事情,您可以使用 NavigatorObserver 来切换是否显示 bottomNavigationBar。这也意味着将 MaterialApp/Scaffold/etc 放在 StatelessWidget 中。
我找到了一个解决方案并且效果很好,但首先要对上面的内容说几句话:
Hero 不是一个选项,因为它不支持所有类型的导航,例如 pushReplacement,我在使用它时 NavigationBar 中的动画有一个错误,可能因为英雄也有内置动画。
解法:
- 我创建了一个名为主页的新屏幕(类似于导航中心)。
- 我们有一个叫做 PageStorageBucket 的东西,它对于存储从一个页面到另一个页面的导航持续存在的每页状态很有用。 enter link description here
homePage.dart:
Widget newsList;
Widget favorites;
Widget profile;
Widget answers;
List<Widget> pages;
Widget currentPage;
final PageStorageBucket bucket = PageStorageBucket();
@override
void initState() {
newsList = NewsList(isFavorite: 0);
favorites = NewsList(isFavorite: 1);
profile = Profile(userID: widget.userID);
answers = Answers();
pages = [newsList, favorites, profile, answers];
currentPage = newsList;
super.initState();
}
所以我们在 PageStorage 存储桶中添加了一些 Widgets(屏幕),然后我们在主页的 Scaffold 中使用它。甚至还有一个地方可以放它。
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageStorage(
child: currentPage,
bucket: bucket,
),
bottomNavigationBar: BottomNavyBar(
currentIndex: currentTab,
onItemSelected: (int index) async {
setState(() {
currentTab = index;
currentPage = pages[index];
});
},
items: [
BottomNavyBarItem(
icon: Icon(Icons.menu),
title: Text('Новости'),
activeColor: Colors.blue,
inactiveColor: Colors.black
),
BottomNavyBarItem(
icon: Icon(Icons.favorite_border),
title: Text('Избранное'),
activeColor: Colors.red,
inactiveColor: Colors.black
),
],
),
);
}
}
效果很好。
- homePage Scaffold 是持久的,并且在重定向到另一个页面时不会重新呈现,因此我们可以将导航栏与动画和其他任何东西一起使用。
- 我们可以选择将哪些页面包含在此范围内。
- 我们仍然可以在这些屏幕中使用 Navigator.push 和其他内容
- 可以使用multi-scaffold,比如当你需要不同的appBar时,只需删除homePage的appBar,它就会从打开的屏幕中使用一个appBar。
我的实现:
main.dart: - 它构建了多脚手架(底部导航栏正在 UI 树上方的所有屏幕上创建)
runApp(MaterialApp(
debugShowCheckedModeBanner: false,
title: "WP-seven",
builder: (context, child) {
return Scaffold(
bottomNavigationBar: NavyBottomBar(navigator: (child.key as GlobalKey<NavigatorState>)),
body: child,
);
},
home: NewsList(0),
));
NavyBottomBar.dart:为导航栏小部件分隔 class。 这里我们有一个全局导航键,用于 main.dart 以连接到每个 child 的导航器(child 是每个屏幕小部件。)
final GlobalKey<NavigatorState> navigator;
所以还有一个打开页面的逻辑,但是上面的代码足以在每个屏幕上显示 bottomNavigationBar 并能够导航。
问题是我不需要在每个屏幕上都有这个底部导航,应该有办法在某些屏幕上关闭导航栏。
可能有不同的方法来实现这个结果..?
对此最简单的回答是,您应该只在每个单独的页面上构建底部导航栏。导航栏本身可以放入它自己的 Stateless 或 StatefulWidget 中,这样您就不必每次都完全指定它。如果你想让它看起来像是在页面之间持续存在,你可以使用 flutter 的 Hero 功能来做到这一点。
如果这不是您愿意做的事情,您可以使用 NavigatorObserver 来切换是否显示 bottomNavigationBar。这也意味着将 MaterialApp/Scaffold/etc 放在 StatelessWidget 中。
我找到了一个解决方案并且效果很好,但首先要对上面的内容说几句话:
Hero 不是一个选项,因为它不支持所有类型的导航,例如 pushReplacement,我在使用它时 NavigationBar 中的动画有一个错误,可能因为英雄也有内置动画。
解法:
- 我创建了一个名为主页的新屏幕(类似于导航中心)。
- 我们有一个叫做 PageStorageBucket 的东西,它对于存储从一个页面到另一个页面的导航持续存在的每页状态很有用。 enter link description here
homePage.dart:
Widget newsList;
Widget favorites;
Widget profile;
Widget answers;
List<Widget> pages;
Widget currentPage;
final PageStorageBucket bucket = PageStorageBucket();
@override
void initState() {
newsList = NewsList(isFavorite: 0);
favorites = NewsList(isFavorite: 1);
profile = Profile(userID: widget.userID);
answers = Answers();
pages = [newsList, favorites, profile, answers];
currentPage = newsList;
super.initState();
}
所以我们在 PageStorage 存储桶中添加了一些 Widgets(屏幕),然后我们在主页的 Scaffold 中使用它。甚至还有一个地方可以放它。
@override
Widget build(BuildContext context) {
return Scaffold(
body: PageStorage(
child: currentPage,
bucket: bucket,
),
bottomNavigationBar: BottomNavyBar(
currentIndex: currentTab,
onItemSelected: (int index) async {
setState(() {
currentTab = index;
currentPage = pages[index];
});
},
items: [
BottomNavyBarItem(
icon: Icon(Icons.menu),
title: Text('Новости'),
activeColor: Colors.blue,
inactiveColor: Colors.black
),
BottomNavyBarItem(
icon: Icon(Icons.favorite_border),
title: Text('Избранное'),
activeColor: Colors.red,
inactiveColor: Colors.black
),
],
),
);
}
}
效果很好。
- homePage Scaffold 是持久的,并且在重定向到另一个页面时不会重新呈现,因此我们可以将导航栏与动画和其他任何东西一起使用。
- 我们可以选择将哪些页面包含在此范围内。
- 我们仍然可以在这些屏幕中使用 Navigator.push 和其他内容
- 可以使用multi-scaffold,比如当你需要不同的appBar时,只需删除homePage的appBar,它就会从打开的屏幕中使用一个appBar。