我想在所有屏幕上保留导航抽屉。对此有很多疑问,但我的问题与其他问题几乎没有什么不同。 Persisting AppBar Drawer across all Pages Flutter
我有一个导航抽屉,其中包含名为A,B和C的项目列表。在导航抽屉中单击A时,屏幕A打开,并且B和C分别相同。现在C屏幕上有一个按钮,然后单击按钮我将转到屏幕D,尽管屏幕D显示了“导航抽屉”图标,但抽屉从未打开过。我尝试在调用抽屉的方法中打印一条语句,并且打印语句可以打印,但是抽屉从不打开。以下是我的代码
我有一个基类,其抽屉如下
class BaseScreen extends StatefulWidget {
final List<Menu> menuList;
final String userType;
final String userId;
const BaseScreen({Key key, this.menuList, this.userType, this.userId})
: super(key: key);
@override
BaseScreenState createState() {
return new BaseScreenState();
}
}
class BaseScreenState extends State<BaseScreen> {
String screenNameSelected = "A";
@override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
_getDrawerItemWidget(screenNameSelected),
],
),
drawer: SizedBox(
width: 100,
child: Drawer(
child: ListView.separated(
separatorBuilder: (context, index) => Material(
elevation: 2,
shadowColor: shadow,
child: Divider(
color: white,
),
),
itemBuilder: (BuildContext context, int index) {
return ListTile(
onTap: () {
openScreen(
widget.menuList[index].title,
widget.userId,
MenuList.returnLoginType(widget.userType).toString(),
context);
Navigator.pop(context);
},
title: Padding(
padding: const EdgeInsets.only(top: 8),
child: Image.asset(
widget.menuList[index].image,
width: 35,
height: 35,
),
),
);
},
itemCount: widget.menuList?.length ?? 0,
shrinkWrap: true,
physics: BouncingScrollPhysics(),
),
),
),
);
}
_getDrawerItemWidget(String selectedScreenName) {
switch (selectedScreenName) {
case A:
return A();
case B:
return B();
case C:
return C();
default:
return Container();
}
}
void openScreen(String screenName, String userId, String loginType,
BuildContext context) {
if (screenName.toLowerCase() == "A".toLowerCase()) {
setState(() {
screenNameSelected = "A";
});
} else if (screenName.toLowerCase() == "B".toLowerCase()) {
setState(() {
screenNameSelected = "B";
});
} else if (screenName.toLowerCase() == "C".toLowerCase()) {
setState(() {
screenNameSelected = "C";
});
}
}
}
由于我的应用栏高度定制,我为应用栏创建了自定义类
class CustomAppBar extends StatelessWidget {
final String subTitleText;
final String subTitleImage;
const CustomAppBar(
{Key key, @required this.subTitleText, @required this.subTitleImage})
: super(key: key);
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
SafeArea(
child: Column(
children: <Widget>[
Builder(builder: (context) => customAppBar(context)),
SizedBox(
height: 5.0,
),
subTitleRow(
subTitleText,
subTitleImage,
)
],
),
),
],
);
}
}
Widget subTitleRow(String subtitleText, String subtitleImage) {
.........
}
Widget customAppBar(BuildContext context) {
return Material(
elevation: 5.0,
shadowColor: shadow,
child: SafeArea(
child: Stack(
children: <Widget>[
Row(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Image.asset(
"images/toolbar_logo.webp",
width: 80,
height: 50,
),
],
),
IconButton(
icon: Image.asset("images/menu.webp"),
onPressed: () {
Scaffold.of(context).openDrawer();
},
iconSize: 20,
),
],
),
),
);
}
现在我的A,B和C类没有脚手架,但我为D类提供了脚手架,我认为这是造成问题的原因。不为D类提供脚手架不会提供正确的布局
A,B和C类的代码如下
class A extends StatelessWidget {
@override
Widget build(BuildContext context) {
return ShortBioProvider(
child: Column(
children: <Widget>[
CustomAppBar(
subTitleImage: "images/settings.webp",
subTitleText: SETTINGS.toUpperCase(),
),
SizedBox(
height: 20,
),
SettingsList(),
],
),
);
}
}
B和C与A非常相似。
现在可以使用D类代码
class D extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Scaffold(body: Column(children: <Widget>[
CustomAppBar(
subTitleImage: "images/settings.webp",
subTitleText: D.toUpperCase(),
),
SizedBox(
height: 20,
),
........
],),);
}
}
我对上述类进行了很多编辑,因此可能在此处或此处缺少括号或分号
答案 0 :(得分:1)
嗯,现在您已经添加了代码,很有意义。
发生的事情是,在D的情况下,您有两个不同的支架:
BaseScreenState
--> Scaffold 1
--> drawer
body
--> stack
--> D
--> Scaffold 2
-->CustomAppBar ....
当您执行Scaffold.of(context)时,它将在树中向上查找以找到最近的支架,在这种情况下,该支架恰好是没有抽屉的Scaffold 2。 D类中的脚手架似乎没有任何作用,因此删除它应该可以解决您的问题。
如何
您的代码中存在一些更严重的问题。您几乎永远不应使用堆栈在页面之间进行切换。一方面,flutter无法像这样那样缓存小部件,但是它也消除了诸如屏幕过渡之类的事情。
您应该做的是为应用程序中的每个页面制作一个包含脚手架,抽屉,应用程序栏等的页面,然后使用导航器在这些页面之间切换。 (请注意,仅因为您为每个页面都创建了一个小部件,并不意味着不能共享这些组件。)
扑朔迷离的架构如下:
onGenerateRoute
中-我发现,与动态构建事物相比,它可以更清楚轻松地讲述正在发生的事情。 其他一些需要注意的事情是:
希望对您有帮助!