PopUpWindow弹出后如何调用setState(重建页面)?
How to call setState (rebuild page), after pop of PopUpWindow?
我正在尝试 update/rebuild 弹出窗口 window 弹出窗口 window 下的路由,使用 Navigator.pop(上下文)。在弹出窗口 window 上,用户可以向列表中添加内容,在下方(页面)的路由中,添加的项目显示在 ListView 中。所以更具体地说,我需要我的 ListView 与实际列表保持同步。但是我还没有尝试过任何东西,都奏效了。
如前所述,我已经尝试了很多东西,包括:
didPopNext()(使用 RouteAware)、changedExternalState(我不太了解)、尝试传递仅包含 setState(() {}) 的函数以及其他内容。
希望有人能帮助我如何在弹出 window 弹出时重建 ListView。
提前致谢。
这个例子应该很好地总结了我的问题(无法向您展示实际的代码,因为它已经超过 2.000 行,但问题的核心要素应该在这里):
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: MyPage()));
class PopupLayout extends ModalRoute<void> {
@override
Duration get transitionDuration => Duration(milliseconds: 300);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
bool get semanticsDismissible => true;
@override
Color get barrierColor =>
bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
@override
String get barrierLabel => null;
@override
bool get maintainState => false;
double top;
double bottom;
double left;
double right;
Color bgColor;
final Widget child;
PopupLayout(
{Key key,
this.bgColor,
@required this.child,
this.top,
this.bottom,
this.left,
this.right});
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
if (top == null) this.top = 10;
if (bottom == null) this.bottom = 20;
if (left == null) this.left = 20;
if (right == null) this.right = 20;
return GestureDetector(
onTap: () {},
child: Material(
type: MaterialType.transparency,
child: _buildOverlayContent(context),
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Container(
margin: EdgeInsets.only(
bottom: this.bottom,
left: this.left,
right: this.right,
top: this.top),
child: child,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
}
class PopupContent extends StatefulWidget {
final Widget content;
PopupContent({
Key key,
this.content,
}) : super(key: key);
_PopupContentState createState() => _PopupContentState();
}
class _PopupContentState extends State<PopupContent> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: widget.content,
);
}
}
popupContent(BuildContext context, Widget widget,
{BuildContext popupContext}) {
Navigator.push(
context,
PopupLayout(
top: 120,
left: 20,
right: 20,
bottom: 120,
child: PopupContent(
content: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: widget,
),
),
),
);
}
Widget popupWidget(BuildContext context) {
return new Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("This is a popupPage"),
FlatButton(
onPressed: () {
list.add("Irrelevant");
Navigator.pop(context); //The rebuild of the page underneath, needs to be called when this pops
},
child: Text("Press me to change text on home page"),
),
]
),
);
}
List list = [];
class MyPage extends StatefulWidget {
@override
createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Container(
width: 300,
height: 400,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Center(
child: Text(index.toString()),
);
},
),
),
),
Center(
child: FlatButton(
onPressed: () {
popupContent(context, popupWidget(context));
},
child: Text("Press me for popup window"),
),
),
Center(
child: FlatButton(
onPressed: () {
setState(() {});
},
child: Text("Press me to rebuild page (setState)"),
),
),
]
),
);
}
}
您可以在MyPage 中添加一个函数并将其传递给您的popUpWidget。代码:
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(home: MyPage()));
class PopupLayout extends ModalRoute<void> {
@override
Duration get transitionDuration => Duration(milliseconds: 300);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
bool get semanticsDismissible => true;
@override
Color get barrierColor =>
bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
@override
String get barrierLabel => null;
@override
bool get maintainState => false;
double top;
double bottom;
double left;
double right;
Color bgColor;
final Widget child;
PopupLayout(
{Key key,
this.bgColor,
@required this.child,
this.top,
this.bottom,
this.left,
this.right});
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
if (top == null) this.top = 10;
if (bottom == null) this.bottom = 20;
if (left == null) this.left = 20;
if (right == null) this.right = 20;
return GestureDetector(
onTap: () {},
child: Material(
type: MaterialType.transparency,
child: _buildOverlayContent(context),
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Container(
margin: EdgeInsets.only(
bottom: this.bottom,
left: this.left,
right: this.right,
top: this.top),
child: child,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
}
class PopupContent extends StatefulWidget {
final Widget content;
PopupContent({
Key key,
this.content,
}) : super(key: key);
_PopupContentState createState() => _PopupContentState();
}
class _PopupContentState extends State<PopupContent> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: widget.content,
);
}
}
popupContent(BuildContext context, Widget widget, {BuildContext popupContext}) {
Navigator.push(
context,
PopupLayout(
top: 120,
left: 20,
right: 20,
bottom: 120,
child: PopupContent(
content: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: widget,
),
),
),
);
}
Widget popupWidget(BuildContext context, Function callback) {
//Pass The Function Here //////////////////////
return new Container(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text("This is a popupPage"),
FlatButton(
onPressed: () {
list.add("Irrelevant");
callback(); // Call It Here /////////////////////////
Navigator.pop(
context); //The rebuild of the page underneath, needs to be called when this pops
},
child: Text("Press me to change text on home page"),
),
]),
);
}
List list = [];
class MyPage extends StatefulWidget {
@override
createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
//The Calback Function //////////////////////////
void callback() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Container(
width: 300,
height: 400,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Center(
child: Text(index.toString()),
);
},
),
),
),
Center(
child: FlatButton(
onPressed: () {
popupContent(context, popupWidget(context, this.callback)); //Passing the Function here ////////////
},
child: Text("Press me for popup window"),
),
),
Center(
child: FlatButton(
onPressed: () {
setState(() {});
},
child: Text("Press me to rebuild page (setState)"),
),
),
]),
);
}
}
我正在尝试 update/rebuild 弹出窗口 window 弹出窗口 window 下的路由,使用 Navigator.pop(上下文)。在弹出窗口 window 上,用户可以向列表中添加内容,在下方(页面)的路由中,添加的项目显示在 ListView 中。所以更具体地说,我需要我的 ListView 与实际列表保持同步。但是我还没有尝试过任何东西,都奏效了。
如前所述,我已经尝试了很多东西,包括: didPopNext()(使用 RouteAware)、changedExternalState(我不太了解)、尝试传递仅包含 setState(() {}) 的函数以及其他内容。
希望有人能帮助我如何在弹出 window 弹出时重建 ListView。
提前致谢。
这个例子应该很好地总结了我的问题(无法向您展示实际的代码,因为它已经超过 2.000 行,但问题的核心要素应该在这里):
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(
home: MyPage()));
class PopupLayout extends ModalRoute<void> {
@override
Duration get transitionDuration => Duration(milliseconds: 300);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
bool get semanticsDismissible => true;
@override
Color get barrierColor =>
bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
@override
String get barrierLabel => null;
@override
bool get maintainState => false;
double top;
double bottom;
double left;
double right;
Color bgColor;
final Widget child;
PopupLayout(
{Key key,
this.bgColor,
@required this.child,
this.top,
this.bottom,
this.left,
this.right});
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
if (top == null) this.top = 10;
if (bottom == null) this.bottom = 20;
if (left == null) this.left = 20;
if (right == null) this.right = 20;
return GestureDetector(
onTap: () {},
child: Material(
type: MaterialType.transparency,
child: _buildOverlayContent(context),
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Container(
margin: EdgeInsets.only(
bottom: this.bottom,
left: this.left,
right: this.right,
top: this.top),
child: child,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
}
class PopupContent extends StatefulWidget {
final Widget content;
PopupContent({
Key key,
this.content,
}) : super(key: key);
_PopupContentState createState() => _PopupContentState();
}
class _PopupContentState extends State<PopupContent> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: widget.content,
);
}
}
popupContent(BuildContext context, Widget widget,
{BuildContext popupContext}) {
Navigator.push(
context,
PopupLayout(
top: 120,
left: 20,
right: 20,
bottom: 120,
child: PopupContent(
content: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: widget,
),
),
),
);
}
Widget popupWidget(BuildContext context) {
return new Container(
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text("This is a popupPage"),
FlatButton(
onPressed: () {
list.add("Irrelevant");
Navigator.pop(context); //The rebuild of the page underneath, needs to be called when this pops
},
child: Text("Press me to change text on home page"),
),
]
),
);
}
List list = [];
class MyPage extends StatefulWidget {
@override
createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Container(
width: 300,
height: 400,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Center(
child: Text(index.toString()),
);
},
),
),
),
Center(
child: FlatButton(
onPressed: () {
popupContent(context, popupWidget(context));
},
child: Text("Press me for popup window"),
),
),
Center(
child: FlatButton(
onPressed: () {
setState(() {});
},
child: Text("Press me to rebuild page (setState)"),
),
),
]
),
);
}
}
您可以在MyPage 中添加一个函数并将其传递给您的popUpWidget。代码:
import 'package:flutter/material.dart';
void main() => runApp(new MaterialApp(home: MyPage()));
class PopupLayout extends ModalRoute<void> {
@override
Duration get transitionDuration => Duration(milliseconds: 300);
@override
bool get opaque => false;
@override
bool get barrierDismissible => false;
@override
bool get semanticsDismissible => true;
@override
Color get barrierColor =>
bgColor == null ? Colors.black.withOpacity(0.5) : bgColor;
@override
String get barrierLabel => null;
@override
bool get maintainState => false;
double top;
double bottom;
double left;
double right;
Color bgColor;
final Widget child;
PopupLayout(
{Key key,
this.bgColor,
@required this.child,
this.top,
this.bottom,
this.left,
this.right});
@override
Widget buildPage(
BuildContext context,
Animation<double> animation,
Animation<double> secondaryAnimation,
) {
if (top == null) this.top = 10;
if (bottom == null) this.bottom = 20;
if (left == null) this.left = 20;
if (right == null) this.right = 20;
return GestureDetector(
onTap: () {},
child: Material(
type: MaterialType.transparency,
child: _buildOverlayContent(context),
),
);
}
Widget _buildOverlayContent(BuildContext context) {
return Container(
margin: EdgeInsets.only(
bottom: this.bottom,
left: this.left,
right: this.right,
top: this.top),
child: child,
);
}
@override
Widget buildTransitions(BuildContext context, Animation<double> animation,
Animation<double> secondaryAnimation, Widget child) {
return FadeTransition(
opacity: animation,
child: ScaleTransition(
scale: animation,
child: child,
),
);
}
}
class PopupContent extends StatefulWidget {
final Widget content;
PopupContent({
Key key,
this.content,
}) : super(key: key);
_PopupContentState createState() => _PopupContentState();
}
class _PopupContentState extends State<PopupContent> {
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
return Container(
child: widget.content,
);
}
}
popupContent(BuildContext context, Widget widget, {BuildContext popupContext}) {
Navigator.push(
context,
PopupLayout(
top: 120,
left: 20,
right: 20,
bottom: 120,
child: PopupContent(
content: Scaffold(
backgroundColor: Colors.white,
resizeToAvoidBottomInset: false,
body: widget,
),
),
),
);
}
Widget popupWidget(BuildContext context, Function callback) {
//Pass The Function Here //////////////////////
return new Container(
child:
Column(mainAxisAlignment: MainAxisAlignment.center, children: <Widget>[
Text("This is a popupPage"),
FlatButton(
onPressed: () {
list.add("Irrelevant");
callback(); // Call It Here /////////////////////////
Navigator.pop(
context); //The rebuild of the page underneath, needs to be called when this pops
},
child: Text("Press me to change text on home page"),
),
]),
);
}
List list = [];
class MyPage extends StatefulWidget {
@override
createState() => MyPageState();
}
class MyPageState extends State<MyPage> {
//The Calback Function //////////////////////////
void callback() {
setState(() {});
}
@override
Widget build(BuildContext context) {
return new Scaffold(
body: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Center(
child: Container(
width: 300,
height: 400,
child: ListView.builder(
itemCount: list.length,
itemBuilder: (BuildContext context, int index) {
return Center(
child: Text(index.toString()),
);
},
),
),
),
Center(
child: FlatButton(
onPressed: () {
popupContent(context, popupWidget(context, this.callback)); //Passing the Function here ////////////
},
child: Text("Press me for popup window"),
),
),
Center(
child: FlatButton(
onPressed: () {
setState(() {});
},
child: Text("Press me to rebuild page (setState)"),
),
),
]),
);
}
}