如何在Flutter的PageView组件间传递两个下拉按钮的数据?
问题:Flutter引导页中Page2下拉选择值传递给Page0的问题
我正在构建一个包含三个页面的引导功能:
- Page0包含
PageView Widget,通过widgets.add()方法加载Page1和Page2 - Page1是欢迎页面
- Page2包含两个下拉按钮,需要在
onChanged触发后将选中值传递给Page0
Page0 代码
class Page0 extends StatefulWidget { @override State<StatefulWidget> createState() => new _Page0State(); } class _Page0State extends State<Page0> { late UserPreferencesArguments? args; int currentPage = 0; static const _kDuration = const Duration(milliseconds: 500); static const _kCurve = Curves.ease; PageController pageController = PageController(); final globalScaffoldKey = GlobalKey<ScaffoldState>(); List<Widget> widgets = []; @override void initState() { super.initState(); init(); } init() async { widgets.add(Page1()); widgets.add(Page2()); } @override void dispose() { //pageController?.dispose(); super.dispose(); } @override void setState(fn) { if (mounted) super.setState(fn); } @override Widget build(BuildContext context) { args = ModalRoute.of(context)?.settings.arguments as UserPreferencesArguments?; return SafeArea( child: Scaffold( key: globalScaffoldKey, body: Stack( children: [ Container( child: PageView( scrollDirection: Axis.horizontal, controller: pageController, children: widgets, onPageChanged: (i) { currentPage = i; setState(() {}); }, ), ), Positioned( child: Container( child: ElevatedButton( style: ElevatedButton.styleFrom( backgroundColor: Colors.black, shadowColor: Colors.grey, ), onPressed: () { if (currentPage == 1) { updateAttributes(args?.aaa, args?.bbb); Navigator.pushReplacementNamed(context, '/homepage'); } else { pageController.nextPage(duration: _kDuration, curve: _kCurve); } }, child: Text(currentPage == 1 ? 'Finish' : "Next",), ), ), ), ], ) ), ); } updateAttributes(aaa, bbb) async { debugPrint('devid: ${aaa}'); debugPrint('devid: ${bbb}'); } }
Page2 代码
class Page2 extends StatefulWidget { @override State<StatefulWidget> createState() => new _Page2State(); } class _Page2State extends State<Page2> { String aaaImportValue = ""; String? _valAAA; List _aaaList = ["1", "2" ]; String bbbImportValue = ""; String? _valBBB; List _bbbList = ["3", "4" ]; @override void initState() { super.initState(); init(); } init() async {} @override Widget build(BuildContext context) { return Column( children: [ Container( child: DropdownButton<String>( hint: Text("Select").tr(), value: _valAAA, items: _aaaList.map((value) { return DropdownMenuItem<String>( child: Text(value), value: value, ); }).toList(), onChanged: (String? value) { setState(() { _valAAA = value!; }); }, ), ), Container( child: DropdownButton<String>( hint: Text("Select").tr(), value: _valBBB, items: _bbbList.map((value) { return DropdownMenuItem<String>( child: Text(value), value: value, ); }).toList(), onChanged: (String? value) { setState(() { _valBBB = value!; }); }, ), ), ], ); } }
尝试过的无效方法
我尝试在下拉按钮的onChanged中通过路由跳转传参,但这样只会重新导航到Page0,无法把值传递给当前已存在的Page0实例:
onChanged: (String? value) { setState(() { _valBBB = value!; if(_valBBB != null){ Navigator.pushNamed(context, "/Page0", arguments: UserPreferencesArguments(_valAAA, _valBBB)); } }); },
解决方案
因为Page2是Page0中PageView的子组件,无需通过路由跳转传参,直接用回调函数即可实现值的传递,步骤如下:
- 修改Page2的StatefulWidget,添加回调参数
class Page2 extends StatefulWidget { // 定义回调函数,用于传递选中的两个值 final Function(String? aaa, String? bbb)? onValuesChanged; const Page2({Key? key, this.onValuesChanged}) : super(key: key); @override State<StatefulWidget> createState() => new _Page2State(); }
- 在Page2的下拉按钮onChanged中触发回调
更新两个下拉按钮的onChanged逻辑,每次选中值变化时调用回调把值传给Page0:
// AAA下拉按钮的onChanged onChanged: (String? value) { setState(() { _valAAA = value!; }); // 触发回调传递当前选中的两个值 widget.onValuesChanged?.call(_valAAA, _valBBB); }, // BBB下拉按钮的onChanged onChanged: (String? value) { setState(() { _valBBB = value!; }); // 触发回调传递当前选中的两个值 widget.onValuesChanged?.call(_valAAA, _valBBB); },
- 在Page0中初始化Page2时传入回调
修改Page0的init方法,传入回调函数接收Page2传来的值并更新本地状态:
init() async { widgets.add(Page1()); widgets.add(Page2( onValuesChanged: (aaa, bbb) { setState(() { // 保存Page2传递过来的值 args = UserPreferencesArguments(aaa, bbb); }); }, )); }
- 调整Page0的按钮逻辑和更新方法
简化updateAttributes方法,直接使用本地保存的args值:
updateAttributes() async { debugPrint('aaa: ${args?.aaa}'); debugPrint('bbb: ${args?.bbb}'); } // 同时修改按钮的onPressed逻辑 onPressed: () { if (currentPage == 1) { updateAttributes(); Navigator.pushReplacementNamed(context, '/homepage'); } else { pageController.nextPage(duration: _kDuration, curve: _kCurve); } },
其他可选方案
如果后续页面结构更复杂,也可以使用ValueNotifier或状态管理工具(如Provider)来实现跨组件状态共享,但对于当前的父子组件传值场景,回调函数是最直接高效的方式。
内容的提问来源于stack exchange,提问作者BradG
相关产品推荐
相关产品推荐

