You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中DropdownMenu添加Navigator.push后值不更新及传值需求

问题解决:Dropdown选择后值不更新且跳转页面的问题

问题现象

DropdownMenu原本运行正常,在setState()中添加Navigator.push后,选择选项下拉菜单值不更新,但页面跳转和数据传递功能正常。需要实现下拉菜单值更新的同时完成页面跳转,并根据选择向另一个Stateful类传递对应数据。

问题原因

  1. 在setState回调内直接调用Navigator.push,页面会立即跳转,原页面的状态更新(Dropdown选中值变更)来不及渲染就被切换走,导致视觉上看不到值更新。
  2. 当前代码中跳转时的经纬度是硬编码值,没有和选中的Gate关联,无法实现根据选择传递对应数据的需求。
  3. DropdownButtonExample作为独立的StatefulWidget,与homepage的状态完全隔离,不利于数据同步和传递。

解决方案

  1. 先更新状态,再执行跳转:将Navigator.push移出setState回调,或者使用WidgetsBinding.instance.addPostFrameCallback确保状态更新渲染完成后再跳转。
  2. 建立Gate与经纬度的映射:为每个Gate配置对应的经纬度,实现选择不同Gate传递对应数据。
  3. 优化状态管理:将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.04 06:35:18