Rai*_*ado 5 flutter flutter-layout flutter-web flutter-widget
我正在研究 Flutter 响应式 Web UI。我想在移动和桌面屏幕宽度的特定屏幕宽度上关闭打开的抽屉,所以如果我拉伸浏览器,抽屉应该关闭。
比如我打开抽屉(屏幕宽度小于500)
而当屏幕宽度大于 500 时,我希望打开的抽屉自动关闭。
注意:当抽屉打开时。我已经有一个代码来检查是否显示按钮菜单抽屉的屏幕宽度。但基本上,当用户打开抽屉然后突然拉伸浏览器时,抽屉应该关闭。
代码如下。谢谢您的帮助
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size.width;
return Scaffold(
drawer: Drawer(),
body: CustomNavBar(screenSize: size),
);
}
}
class CustomNavBar extends StatefulWidget {
final double screenSize;
const CustomNavBar({Key key, this.screenSize}) : super(key: key);
@override
_CustomNavBarState createState() => _CustomNavBarState();
}
class _CustomNavBarState extends State<CustomNavBar> {
@override
Widget build(BuildContext context) {
if (Scaffold.of(context).isDrawerOpen && widget.screenSize > 500) {
print("Drawer is Opened");
Scaffold.of(context).openEndDrawer(); //animation error
setState(() {});
}
return widget.screenSize > 500
? Container(color: Colors.red) //desktop screen
: Center(
//mobile screen
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
您不必手动关闭抽屉。当屏幕宽度小于 500 时,为什么不去掉抽屉?
class SampleDrawer extends StatelessWidget {
final GlobalKey<ScaffoldState> k = GlobalKey();
@override
Widget build(BuildContext context) {
// new
final size = MediaQuery.of(context).size.width;
if (k.currentState.isDrawerOpen && size < 500) {
Navigator.pop(context); // close drawer
}
return Scaffold(
key: k,
drawer: size > 500 ? Drawer() : null,
body: CustomNavBar(),
);
}
}
class CustomNavBar extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size.width;
return size > 500
? Container(color: Colors.red) //desktop screen
: Center( //mobile screen
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
每当设备宽度发生变化时都会重新构建 Scaffold,如果宽度小于 500,则会自动省略抽屉。
你的代码就足够了。只需对您的代码进行一些更改
把这个包Scaffold.of(context).openEndDrawer();起来
WidgetsBinding.instance.addPostFrameCallback((_) {
Scaffold.of(context).openEndDrawer(); //No Error
///The Error was coming, As you're trying to build a widget when it is
///rebuilding widget Tree due to the change in the width of the browser.
///Wrapping it inside ensures that the code will run after the build.
});
Run Code Online (Sandbox Code Playgroud)
不要使用setState(() {});
使用 520 而不是 500
错误出现了,当您尝试构建一个小部件时,由于浏览器宽度的变化而正在重建小部件树。将其包装
Scaffold.of(context).openEndDrawer();在内部WidgetsBinding.instance.addPostFrameCallback((_) {});可确保代码在构建小部件后运行。
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final size = MediaQuery.of(context).size.width;
print(size);
return Scaffold(
drawer: Drawer(),
body: CustomNavBar(
screenSize: size,
),
);
}
}
class CustomNavBar extends StatefulWidget {
final double screenSize;
const CustomNavBar({
Key key,
this.screenSize,
}) : super(key: key);
@override
_CustomNavBarState createState() => _CustomNavBarState();
}
class _CustomNavBarState extends State<CustomNavBar> {
@override
Widget build(BuildContext context) {
if (Scaffold.of(context).isDrawerOpen && widget.screenSize > 520) {
print("Drawer is Opened");
WidgetsBinding.instance.addPostFrameCallback((_) {
Scaffold.of(context).openEndDrawer(); //No Error
///The error was coming, As you're trying to build a widget when it is
///rebuilding widget Tree due to the change in the width of the browser.
///Wrapping it inside ensure that the code will run after the build.
});
// Don't call setState((){}); Not Required;
// as every time you change the width it rebuilds all the widget again
// setState(() {});
}
return widget.screenSize > 520
? Container(color: Colors.red) //desktop screen
: Center(
//mobile screen
child: IconButton(
icon: Icon(Icons.menu),
onPressed: () => Scaffold.of(context).openDrawer(),
),
);
}
}
Run Code Online (Sandbox Code Playgroud)
The following assertion was thrown while notifying status listeners for
AnimationController:
setState() or markNeedsBuild() called during build.
This Scaffold widget cannot be marked as needing to build because the framework is
already in the
process of building widgets. A widget can be marked as needing to be built during
the build phase
only if one of its ancestors is currently building. This exception is allowed
because the framework
builds parent widgets before children, which means a dirty descendant will always be
built.
Otherwise, the framework might not visit this widget during this build phase.
The widget on which setState() or markNeedsBuild() was called was:
Scaffold
The widget which was currently being built when the offending call was made was:
CustomNavBar
Run Code Online (Sandbox Code Playgroud)
使用响应式 UI 的布局生成器。
@override
Widget build(BuildContext context) {
return LayoutBuilder(
builder: (context, constraints) {
if (constraints.maxWidth > 800) {
return XScreen();
} else if (constraints.maxWidth < 1200 && constraints.maxWidth > 800) {
return Yscreen()?? ZScreen();
} else {
return XScreen()?? ZScreeen();
}
},
);
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
694 次 |
| 最近记录: |