Flutter中DropdownMenu添加Navigator.push后值不更新及传值需求
问题解决:Dropdown选择后值不更新且跳转页面的问题
问题现象
DropdownMenu原本运行正常,在setState()中添加Navigator.push后,选择选项下拉菜单值不更新,但页面跳转和数据传递功能正常。需要实现下拉菜单值更新的同时完成页面跳转,并根据选择向另一个Stateful类传递对应数据。
问题原因
- 在
setState回调内直接调用Navigator.push,页面会立即跳转,原页面的状态更新(Dropdown选中值变更)来不及渲染就被切换走,导致视觉上看不到值更新。 - 当前代码中跳转时的经纬度是硬编码值,没有和选中的Gate关联,无法实现根据选择传递对应数据的需求。
DropdownButtonExample作为独立的StatefulWidget,与homepage的状态完全隔离,不利于数据同步和传递。
解决方案
- 先更新状态,再执行跳转:将
Navigator.push移出setState回调,或者使用WidgetsBinding.instance.addPostFrameCallback确保状态更新渲染完成后再跳转。 - 建立Gate与经纬度的映射:为每个Gate配置对应的经纬度,实现选择不同Gate传递对应数据。
- 优化状态管理:将Dropdown的选中状态提升到
homepage层,简化组件间的状态同步逻辑。
修改后的完整代码
import 'package:flutter/material.dart'; import 'package:google_maps_flutter/google_maps_flutter.dart'; // 各Gate对应的经纬度映射表 const Map<String, LatLng> gateLocations = { 'NorthGate 1': LatLng(21.490190928284374, 39.24029335794148), 'NorthGate 2': LatLng(21.489191114466923, 39.24285294444855), 'WestGate 2': LatLng(21.489312801215913, 39.239637004938416), }; const List<String> gatelist = <String>[ 'NorthGate 1', 'NorthGate 2', 'WestGate 2' ]; class Homepage extends StatefulWidget { final double lat; final double lan; const Homepage({Key? mykey, required this.lan, required this.lat}) : super(key: mykey); @override State<Homepage> createState() => _HomepageState(); } class _HomepageState extends State<Homepage> { String selectedGate = gatelist.first; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( toolbarHeight: 60, centerTitle: true, title: const Text( 'Wajeeh', style: TextStyle(fontSize: 28), ), elevation: 10, backgroundColor: const Color.fromARGB(255, 4, 105, 55), leading: Padding( padding: const EdgeInsets.all(6.0), child: Image.asset( 'images/logo2.png', height: 30, ), ), ), backgroundColor: Colors.white, body: Column( children: [ const SizedBox(height: 70), Row( children: [ Expanded( child: Align( alignment: Alignment.topCenter, child: SizedBox( width: 250, child: DropdownButton<String>( hint: const Text("Choose a Gate"), isExpanded: true, value: selectedGate, icon: const Icon(Icons.arrow_drop_down_sharp), style: const TextStyle( color: Color.fromARGB(255, 4, 105, 55)), underline: Container( height: 2, color: const Color.fromARGB(255, 4, 105, 55), ), onChanged: (String? value) { if (value == null) return; // 先更新Dropdown选中状态 setState(() { selectedGate = value; }); // 等待状态更新渲染完成后再执行跳转 WidgetsBinding.instance.addPostFrameCallback((_) { final location = gateLocations[value]!; Navigator.push( context, MaterialPageRoute( builder: (context) => Homepage( lat: location.latitude, lan: location.longitude, ), ), ); }); }, items: gatelist.map<DropdownMenuItem<String>>((String value) { return DropdownMenuItem<String>( value: value, child: Text(value), ); }).toList(), ), ), ), ), ], ), const SizedBox(height: 45), Row( children: [ Expanded( child: Column( children: [ Image.asset('images/full.jpg'), const Text( 'Total Parking', style: TextStyle( fontSize: 22.0, fontWeight: FontWeight.bold, color: Colors.black), ), const Text( '33', style: TextStyle( fontSize: 22.0, fontWeight: FontWeight.bold, color: Color.fromARGB(255, 4, 105, 55)), ), ], ), ), Expanded( child: Column( children: [ Image.asset('images/remain.jpg'), const Text( 'Available Parking', style: TextStyle( fontSize: 22.0, fontWeight: FontWeight.bold, color: Colors.black), ), const Text( "100", style: TextStyle( fontSize: 22.0, fontWeight: FontWeight.bold, color: Color.fromARGB(255, 4, 105, 55)), ), ], ), ) ], ), const SizedBox(height: 70), Row( children: [ Expanded( child: Align( alignment: Alignment.topCenter, child: SizedBox( width: 355, height: 315, child: Stack( children: [ GoogleMap( initialCameraPosition: CameraPosition( target: LatLng(widget.lan, widget.lat), zoom: 16, ), ), Container( alignment: Alignment.topLeft, child: const Icon( Icons.star, color: Color.fromARGB(255, 231, 210, 23), size: 40, ), ), ], ), ), ), ), ], ), ], ), ); } }
关键修改点说明
- 新增
gateLocations映射表,绑定每个Gate对应的经纬度,实现选择不同Gate传递对应数据。 - 将Dropdown组件直接整合到
Homepage中,状态由_HomepageState管理,避免跨组件状态隔离问题。 - 使用
WidgetsBinding.instance.addPostFrameCallback确保Dropdown选中状态更新并渲染完成后,再执行页面跳转,解决值不更新的视觉问题。 - 规范了类名(
homepage改为Homepage),符合Dart语言命名规范。
内容的提问来源于stack exchange,提问作者FATEN SHAKIR ALSHANBARI
相关产品推荐
相关产品推荐

