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

Flutter Google Maps标记点击跳转新页面问题求助

Flutter Google Maps Marker点击无响应问题解决

问题根源

  1. 全局变量导致状态未更新:存储Marker的list是全局变量,在异步请求后添加Marker时未调用setState(),GoogleMap组件无法感知到Marker集合的变化,界面上实际未渲染出可交互的Marker,因此点击无响应。
  2. 状态管理混乱:cLat、cLong等核心状态变量被定义为全局,脱离了StatefulWidget的状态管理机制,容易引发上下文与状态不同步的问题。
  3. GetX路由潜在问题:若根组件未使用GetMaterialApp,GetX的路由功能无法正常工作;同时Marker的onTap回调在异步操作中创建,可能存在上下文绑定异常。

修复步骤

1. 迁移全局变量到State类内部

将与页面状态强相关的list、mapMarkImg、code、cLat、cLong移至_MapPageState类中,避免全局状态污染。

2. 添加Marker后触发UI更新

在异步请求获取数据并添加Marker时,通过setState()通知Flutter更新界面,确保GoogleMap渲染最新的Marker集合。

3. 确保路由功能正常

  • 若使用GetX跳转:需保证main.dart的根组件为GetMaterialApp而非普通MaterialApp。
  • 若使用Navigator跳转:直接使用State类的context即可,无需额外处理。

修改后的完整代码

import 'dart:async';
import 'dart:convert';
import 'package:area_app/main.dart';
import 'package:area_app/pages/home_page.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:geocoding/geocoding.dart';
import 'package:http/http.dart' as http;
import 'package:get/get.dart';

class MapPage extends StatefulWidget {
  final double longitude;
  final double latitude;
  MapPage({Key? key, required this.longitude, required this.latitude})
      : super(key: key);

  @override
  _MapPageState createState() => _MapPageState();
}

class _MapPageState extends State<MapPage> {
  late Completer<GoogleMapController> _controller;
  double? cLat;
  double? cLong;
  String code = "";
  Set<Marker> list = {};
  BitmapDescriptor? mapMarkImg;

  @override
  void initState() {
    super.initState();
    _controller = Completer();
    cLat = widget.latitude;
    cLong = widget.longitude;
  }

  CameraPosition get _kGooglePlex => CameraPosition(
        target: LatLng(cLat!, cLong!),
        zoom: 15.4746,
      );

  @override
  Widget build(BuildContext context) {
    return FutureBuilder(
      future: getCountry(),
      builder: (context, snapshot) {
        return Scaffold(body: getBody());
      },
    );
  }

  Widget getBody() {
    return GoogleMap(
      onCameraMove: (object) {
        setState(() {
          cLat = object.target.latitude;
          cLong = object.target.longitude;
        });
      },
      markers: list,
      mapType: MapType.normal,
      buildingsEnabled: false,
      myLocationButtonEnabled: false,
      initialCameraPosition: _kGooglePlex,
      onMapCreated: (GoogleMapController controller) {
        _controller.complete(controller);
      },
    );
  }

  Future getCountry() async {
    final lat1 = widget.latitude;
    final long1 = widget.longitude;
    mapMarkImg = await BitmapDescriptor.fromAssetImage(
        ImageConfiguration(), 'assets/images/marker.png');
    List<Placemark> placemarks = await placemarkFromCoordinates(lat1, long1);
    Placemark place = placemarks[0];

    if (code != place.isoCountryCode!) {
      code = place.isoCountryCode!;
      var postCodesResponse = await http.get(Uri.parse(
          'https://data.opendatasoft.com/api/records/1.0/search/?dataset=geonames-postal-code%40public&q=${code}&rows=139&facet=country_code&facet=admin_name1&facet=admin_code1&facet=admin_name2'));

      final postCodesJson = jsonDecode(postCodesResponse.body.toString());
      setState(() {
        list.clear(); // 清空旧Marker,避免重复添加
        for (var i in postCodesJson['records']) {
          Marker marker = Marker(
              markerId: MarkerId(i["fields"]["postal_code"].toString()),
              position: LatLng(i["fields"]["latitude"] as double,
                  i["fields"]["longitude"] as double),
              icon: mapMarkImg!,
              onTap: () {
                // 方案1:GetX跳转(需根组件为GetMaterialApp)
                Get.to(HomePage(pCode: i["fields"]["postal_code"].toString()));
                // 方案2:Navigator跳转
                // Navigator.push(context, MaterialPageRoute(
                //   builder: (context) => HomePage(pCode: i["fields"]["postal_code"].toString())
                // ));
              });

          list.add(marker);
        }
      });
    }
  }
}

额外注意事项

  • 使用Navigator跳转时,直接使用State类的context即可,无需额外传递。
  • 添加新Marker前调用list.clear(),可避免重复请求API时生成重复Marker。
  • 确保HomePage的构造函数正确接收并处理pCode参数。

内容的提问来源于stack exchange,提问作者CODERjack

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.23 08:57:14