Flutter中showModalBottomSheet向上一页面传值不生效如何解决?
问题根因
你代码中StatefulBuilder构造参数里的setState是弹窗自身的局部状态更新方法,仅会触发底部弹窗范围内的UI重绘,不会触发父级TestPage的重新构建,因此父页面的Text组件不会展示最新值,只有热重载触发全局重绘时才会更新显示。
解决方案
以下是两种可直接落地的实现方式:
方案1:调用父页面自身的setState
将StatefulBuilder的状态更新方法重命名避免命名冲突,修改父页面状态时调用父类自带的setState即可:
class TestPage extends StatefulWidget { const TestPage({Key? key}) : super(key: key); @override _TestPageState createState() => _TestPageState(); } class _TestPageState extends State<TestPage> { String textResult = ""; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Container( child: Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(textResult), TextButton( onPressed: () { showModalBottomSheet( shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( topRight: Radius.circular(24.0), topLeft: Radius.circular(24.0))), context: context, // 将StatefulBuilder的setState重命名为setModalState,避免和父类setState冲突 builder: (_) => StatefulBuilder( builder: (BuildContext context, StateSetter setModalState) { return Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { // 调用父页面的setState更新状态 setState(() { textResult = "1"; }); Navigator.pop(context); }, child: const Text( 'Done', style: TextStyle( color: Colors.red, fontWeight: FontWeight.bold), ), ), ], ), ), ], ), ); }), ); }, child: const Text('Press')) ], ), ), ), ), ); } }
方案2(更推荐):通过弹窗返回值传参
showModalBottomSheet本身返回一个Future对象,关闭弹窗时可以携带返回值,父页面接收值后再更新自身状态,耦合度更低,可维护性更好:
class TestPage extends StatefulWidget { const TestPage({Key? key}) : super(key: key); @override _TestPageState createState() => _TestPageState(); } class _TestPageState extends State<TestPage> { String textResult = ""; @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Container( child: Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ Text(textResult), TextButton( // 改成async方法接收弹窗返回值 onPressed: () async { // 接收弹窗关闭时返回的结果 final result = await showModalBottomSheet<String>( shape: RoundedRectangleBorder( borderRadius: BorderRadius.only( topRight: Radius.circular(24.0), topLeft: Radius.circular(24.0))), context: context, builder: (_) => Container( child: Column( crossAxisAlignment: CrossAxisAlignment.start, children: [ Padding( padding: const EdgeInsets.all(8.0), child: Row( mainAxisAlignment: MainAxisAlignment.spaceBetween, children: [ GestureDetector( onTap: () { // 关闭弹窗时携带返回值 Navigator.pop(context, "1"); }, child: const Text( 'Done', style: TextStyle( color: Colors.red, fontWeight: FontWeight.bold), ), ), ], ), ), ], ), ), ); // 拿到返回值后更新父页面状态 if (result != null) { setState(() { textResult = result; }); } }, child: const Text('Press')) ], ), ), ), ), ); } }
内容的提问来源于stack exchange,提问作者Mohammed Nabil
相关产品推荐
相关产品推荐

