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

Flutter中点击OpenStreetMap无法跳转Google Maps问题求助

解决FlutterMap包裹InkWell点击无响应及Google Maps跳转失败问题

问题原因分析

  1. FlutterMap拦截触摸事件:你仅禁用了双击缩放,但FlutterMap默认仍会处理拖动、单点击等其他交互,这些事件会拦截上层InkWell的点击回调。
  2. Google Maps URL Scheme不兼容:comgooglemaps://是iOS专属Scheme,Android设备无法识别,导致跳转失败。
  3. url_launcher权限配置缺失:Android 11+和iOS需要额外配置才能允许调用外部应用。

解决方案

1. 禁用FlutterMap所有交互事件

修改FlutterMap的interactionOptions,将交互flags设为InteractiveFlag.none,让地图不处理任何触摸事件,确保InkWell能接收点击:

interactionOptions: const InteractionOptions(
  flags: InteractiveFlag.none,
),

2. 适配跨平台的Google Maps链接

区分Android和iOS生成对应URL,或使用通用网页链接提升兼容性:

import 'dart:io'; // 需导入Platform包

// 区分平台生成专属链接
final Uri googleMapsUri = Platform.isAndroid
    ? Uri.parse(
        "geo:${restaurantDataModel.latitude},${restaurantDataModel.longitude}?q=${restaurantDataModel.latitude},${restaurantDataModel.longitude}"
      )
    : Uri.parse(
        "comgooglemaps://?center=${restaurantDataModel.latitude},${restaurantDataModel.longitude}&zoom=15"
      );

// 可选:通用网页链接(无App时自动打开网页版)
// final Uri googleMapsUri = Uri.parse(
//   "https://www.google.com/maps/search/?api=1&query=${restaurantDataModel.latitude},${restaurantDataModel.longitude}"
// );

3. 配置url_launcher权限

  • Android:在android/app/src/main/AndroidManifest.xml中添加以下内容,声明允许调用Google Maps:
<queries>
  <package android:name="com.google.android.apps.maps" />
</queries>
  • iOS:在ios/Runner/Info.plist中添加以下内容,允许查询Google Maps的Scheme:
<key>LSApplicationQueriesSchemes</key>
<array>
  <string>comgooglemaps</string>
</array>

4. 优化错误处理

替换直接throw的方式,用SnackBar给用户友好提示:

try {
  if (await canLaunchUrl(googleMapsUri)) {
    await launchUrl(
      googleMapsUri,
      mode: LaunchMode.externalApplication, // 指定打开外部应用
    );
  } else {
    // 降级到网页版
    final Uri webUri = Uri.parse(
      "https://www.google.com/maps/search/?api=1&query=${restaurantDataModel.latitude},${restaurantDataModel.longitude}"
    );
    if (await canLaunchUrl(webUri)) {
      await launchUrl(webUri);
    } else {
      throw "无法打开地图链接";
    }
  }
} catch (e) {
  if (mounted) {
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(content: Text("打开地图失败:$e")),
    );
  }
}

修改后的完整代码

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_map/flutter_map.dart';
import 'package:latlong2/latlong.dart';
import 'package:url_launcher/url_launcher.dart';

// ... 你的StatefulWidget代码 ...

SizedBox(
  width: 500,
  height: 300,
  child: InkWell(
    onTap: () async {
      final Uri googleMapsUri = Platform.isAndroid
          ? Uri.parse(
              "geo:${restaurantDataModel.latitude},${restaurantDataModel.longitude}?q=${restaurantDataModel.latitude},${restaurantDataModel.longitude}"
            )
          : Uri.parse(
              "comgooglemaps://?center=${restaurantDataModel.latitude},${restaurantDataModel.longitude}&zoom=15"
            );

      try {
        if (await canLaunchUrl(googleMapsUri)) {
          await launchUrl(
            googleMapsUri,
            mode: LaunchMode.externalApplication,
          );
        } else {
          final Uri webUri = Uri.parse(
            "https://www.google.com/maps/search/?api=1&query=${restaurantDataModel.latitude},${restaurantDataModel.longitude}"
          );
          if (await canLaunchUrl(webUri)) {
            await launchUrl(webUri);
          } else {
            throw "无法打开地图链接";
          }
        }
      } catch (e) {
        if (mounted) {
          ScaffoldMessenger.of(context).showSnackBar(
            SnackBar(content: Text("打开地图失败:$e")),
          );
        }
      }
    },
    child: FlutterMap(
      options: MapOptions(
        initialCenter: LatLng(
          restaurantDataModel.latitude,
          restaurantDataModel.longitude,
        ),
        initialZoom: 15,
        interactionOptions: const InteractionOptions(
          flags: InteractiveFlag.none,
        ),
      ),
      children: [
        openStreetMapTileLayer,
        MarkerLayer(
          markers: [
            Marker(
              point: LatLng(
                restaurantDataModel.latitude,
                restaurantDataModel.longitude,
              ),
              width: 60,
              height: 60,
              alignment: Alignment.centerLeft,
              child: const Icon(
                Icons.location_pin,
                size: 40,
                color: Colors.red,
              ),
            ),
          ],
        ),
      ],
    ),
  ),
);

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 19:47:33