“硬”的方式
管理 AppBar 的最有效方法是将 Scaffold 放置在每个视图中,而不是像您似乎试图做的那样放在包装器中。然后你可以在每个视图中专门控制应用栏。
因此,使用该解决方案,App 将如下所示:
class App extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
builder: OneContext().builder,
home: Home(),
}
}
...和PageWithScaffold 看起来像这样:
class PageWithAppbar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Container(),
);
}
}
...和PageWithoutScaffold 看起来像这样:
class PageWithoutAppbar extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(
body: Container(),
);
}
}
使用 CHANGENOTIFIER 的示例应用
但是,如果需要,您可以选择在包装器内使用 Scoffold。我将这个示例应用程序(所有一个文件)放在一起,以展示使用ChangeNotifier 执行此操作的一种可能方法。主App 向通知程序注册了一个侦听器。当某些事情发生变化时,会为App 触发构建,并使其有机会显示或隐藏 AppBar。我试图在相关位置注释代码以解释发生了什么。
这是示例应用程序:
import 'package:flutter/material.dart';
/// this notifier will be used to trigger changes to the global scaffold
/// - used to show/hide the AppBar as desired
/// - used to display the current view (Widget)
/// - used to display the title in the AppBar
class AppNotifier extends ChangeNotifier {
bool isDisposed = false;
List<VoidCallback> _listeners = [];
bool appBar = true;
Widget currentView;
String title = "Hello, World!";
/// call this method to change which Widget is in view
/// - [title] (default `Hello, World!`) provide a title to show in the AppBar
/// - [includeAppBar] (default `false`) provide to show/hide the AppBar
void show(Widget view, {String title = "Hello, World!", bool includeAppBar = false}) {
appBar = includeAppBar;
currentView = view;
title = title;
notifyListeners();
}
/// call this to show the AppBar
void showAppBar() {
appBar = true;
// the delay is to prevent build errors
Future.delayed(Duration(milliseconds: 25), () {
notifyListeners();
});
}
/// call this to hide the AppBar
void hideAppBar() {
appBar = false;
// the delay is to prevent build errors
Future.delayed(Duration(milliseconds: 25), () {
notifyListeners();
});
}
@override
void addListener(listener) {
_listeners.add(listener);
super.addListener(listener);
}
@override
void dispose() {
_listeners.clear();
isDisposed = true;
super.dispose();
}
@override
void removeListener(listener) {
_listeners.remove(listener);
super.removeListener(listener);
}
}
// this notifer will be used to update the UI
AppNotifier notifier = new AppNotifier();
Future<void> main() async {
runApp(App());
}
class App extends StatefulWidget {
@override
State<StatefulWidget> createState() => _AppState();
}
class _AppState extends State<App> {
// this value is simply used to trigger state changes for the app
int countChanges = 0;
@override
void initState() {
super.initState();
notifier.currentView = StartPage();
notifier.addListener(() {
// when something changes, trigger a rebuild
setState(() {
countChanges = countChanges+1;
});
});
}
// reset the view back to the StartPage
void backToStart() {
notifier.show(StartPage());
}
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: notifier.appBar // if `true` then we will show the AppBar
? AppBar(
title: Text(notifier.title),
centerTitle: true,
leading: notifier.currentView is StartPage ? null : IconButton(
icon: Icon(Icons.arrow_back),
onPressed: () {
// if on the StartPage, this icon will not appear
// on other pages, this allows the user to return to the StartPage
backToStart();
},
),
)
: null,
body: notifier.currentView
)
);
}
}
class StartPage extends StatefulWidget {
StartPage({Key key});
@override
State<StatefulWidget> createState() => _StatePageState();
}
class _StatePageState extends State<StartPage> {
@override
Widget build(BuildContext context) {
if (!notifier.appBar) {
// if the appBar is not showing, make it show
notifier.showAppBar();
}
return Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Welcome to Hello World!"),
Row(children: [
Expanded(
flex: 1,
child:OutlinedButton(
onPressed: () {
// show the PageWithAppBar
notifier.show(PageWithAppBar(), title: "Page w/AppBar");
},
child: Text("Page With Scaffold")
)
),
Expanded(
flex: 1,
child:OutlinedButton(
onPressed: () {
// show the PageWithoutAppBar
notifier.show(PageWithoutAppBar());
},
child: Text("Page Without Scaffold")
)
)
],)
],
)
);
}
}
class PageWithAppBar extends StatefulWidget {
PageWithAppBar({Key key});
@override
State<StatefulWidget> createState() => _PageWithAppBarState();
}
class _PageWithAppBarState extends State<PageWithAppBar> {
@override
Widget build(BuildContext context) {
if (!notifier.appBar) {
// tell the notifier to update the Scaffold and include the AppBar
notifier.showAppBar();
}
return Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height,
child: Text("Hey! This page has an AppBar ?!")
);
}
}
class PageWithoutAppBar extends StatefulWidget {
PageWithoutAppBar({Key key});
@override
State<StatefulWidget> createState() => _PageWithoutAppBarState();
}
class _PageWithoutAppBarState extends State<PageWithoutAppBar> {
@override
Widget build(BuildContext context) {
if (notifier.appBar) {
// tell the notifier to update the Scaffold and dispose of the AppBar
notifier.hideAppBar();
}
return Container(
alignment: Alignment.center,
height: MediaQuery.of(context).size.height,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: [
Text("Boo! This page does not have an AppBar ?."),
OutlinedButton(
onPressed: () {
notifier.show(StartPage());
},
child: Text("Back to Start")
)
],
)
);
}
}
希望这会给您一些关于如何推进您的应用程序的想法。