Flutter中使用apple_maps_flutter从ScreenCoordinate获取LatLng的方法
解决Apple Maps Flutter插件屏幕坐标转经纬度及手绘多边形实现思路
apple_maps_flutter确实没有提供类似Google Maps的getLatLng(ScreenCoordinate)方法,但可以通过以下两种方案实现手绘多边形的需求:
方案一:基于地图可见区域的计算(无原生依赖)
如果你的场景不需要支持地图旋转、倾斜,这种方法足够简单:
- 用
LayoutBuilder获取地图组件的实际宽高,同时监听地图的onCameraMove事件,每次相机移动时记录当前的visibleRegion(包含东北、西南两个角的经纬度)。 - 监听用户触摸事件(用
GestureDetector的onPanStart/onPanUpdate/onPanEnd),获取触摸点相对于地图组件的坐标(Offset)。 - 通过比例计算转换经纬度:
// 假设已获取: // visibleRegion: MapVisibleRegion // mapSize: Size (地图组件的宽高) // touchOffset: Offset (触摸点相对于地图左上角的偏移) double longitude = visibleRegion.southwest.longitude + (touchOffset.dx / mapSize.width) * (visibleRegion.northeast.longitude - visibleRegion.southwest.longitude); double latitude = visibleRegion.northeast.latitude - (touchOffset.dy / mapSize.height) * (visibleRegion.northeast.latitude - visibleRegion.southwest.latitude); LatLng convertedLatLng = LatLng(latitude, longitude); - 注意:地图旋转或倾斜时,这种方法会有明显误差,仅适用于基础场景。
方案二:通过Platform Channel调用原生Apple Maps API(高精度)
Apple Maps的原生MKMapView提供了convert(_:toCoordinateFrom:)方法,可以精准转换屏幕坐标到经纬度,支持所有地图状态:
Flutter端代码
import 'package:flutter/services.dart'; import 'package:apple_maps_flutter/apple_maps_flutter.dart'; final MethodChannel _mapConvertChannel = MethodChannel('your.app.id/map_coordinate_convert'); Future<LatLng?> convertScreenToLatLng(Offset screenOffset) async { try { final Map<String, dynamic>? result = await _mapConvertChannel.invokeMapMethod( 'screenToCoordinate', {'x': screenOffset.dx, 'y': screenOffset.dy}, ); if (result == null) return null; return LatLng(result['latitude'], result['longitude']); } on PlatformException catch (e) { print('坐标转换失败: ${e.message}'); return null; } }
iOS端Swift代码
在AppDelegate.swift或对应的FlutterViewController中实现:
import UIKit import Flutter import MapKit import apple_maps_flutter @UIApplicationMain @objc class AppDelegate: FlutterAppDelegate { override func application( _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? ) -> Bool { let controller : FlutterViewController = window?.rootViewController as! FlutterViewController // 注册MethodChannel let convertChannel = FlutterMethodChannel(name: "your.app.id/map_coordinate_convert", binaryMessenger: controller.binaryMessenger) convertChannel.setMethodCallHandler { [weak self] call, result in guard call.method == "screenToCoordinate", let args = call.arguments as? [String: Double], let x = args["x"], let y = args["y"], // 获取Apple Maps的原生MKMapView实例 let mapView = self?.getAppleMapView(from: controller) else { result(FlutterError(code: "INVALID", message: "参数错误或地图实例未找到", details: nil)) return } let point = CGPoint(x: x, y: y) let coordinate = mapView.convert(point, toCoordinateFrom: mapView) result(["latitude": coordinate.latitude, "longitude": coordinate.longitude]) } GeneratedPluginRegistrant.register(with: self) return super.application(application, didFinishLaunchingWithOptions: launchOptions) } // 从Flutter视图中获取MKMapView private func getAppleMapView(from controller: FlutterViewController) -> MKMapView? { for subview in controller.view.subviews { if let mapView = subview as? MKMapView { return mapView } if subview is FlutterViewController, let nestedMap = getAppleMapView(from: subview as! FlutterViewController) { return nestedMap } } return nil } }
手绘多边形的具体实现步骤
- 维护一个
List<LatLng>用于存储多边形的顶点。 - 用
GestureDetector包裹Apple Maps组件,监听触摸事件:onPanStart:转换触摸点为经纬度,添加到顶点列表。onPanUpdate:实时转换触摸点,更新顶点列表的最后一个点(或添加新点,根据绘制逻辑)。onPanEnd:结束当前线段,准备添加下一个顶点(或闭合多边形)。
- 将顶点列表传入Apple Maps的
Polygon组件,设置polygons: {Polygon(polygonId: PolygonId("handdrawn"), points: _polygonPoints)},实现实时渲染。
内容的提问来源于stack exchange,提问作者Amani Saaduddin
相关产品推荐
相关产品推荐

