Flutter中如何通过地图判断用户地址是否属于我的服务范围
Flutter 服务区域判断实现方案
前置依赖
- 使用
geolocator包用于获取用户当前定位 - 如需不规则多边形判断可直接使用内置射线法逻辑,无需额外依赖地图SDK
核心实现步骤
1. 获取用户当前定位
import 'package:geolocator/geolocator.dart'; Future<Position?> getUserLocation() async { bool serviceEnabled; LocationPermission permission; // 检查位置服务是否开启 serviceEnabled = await Geolocator.isLocationServiceEnabled(); if (!serviceEnabled) { return null; } permission = await Geolocator.checkPermission(); if (permission == LocationPermission.denied) { permission = await Geolocator.requestPermission(); if (permission == LocationPermission.denied) { return null; } } if (permission == LocationPermission.deniedForever) { return null; } return await Geolocator.getCurrentPosition(); }
2. 规则圆形服务区域判断
如果你的服务区域是规则圆形,直接通过坐标距离计算即可:
// 提前配置服务区域中心点、服务半径(单位:米) const double serviceCenterLat = 30.2741; const double serviceCenterLng = 120.1551; const double serviceRadius = 5000; bool checkInCircleArea(Position userPos) { double distance = Geolocator.distanceBetween( userPos.latitude, userPos.longitude, serviceCenterLat, serviceCenterLng, ); return distance <= serviceRadius; }
3. 不规则多边形服务区域判断
如果是自定义多边形服务区域,使用射线法判断坐标是否在多边形内:
class LatLng { final double latitude; final double longitude; LatLng(this.latitude, this.longitude); } // 示例自定义多边形服务区域顶点坐标 List<LatLng> servicePolygon = [ LatLng(30.28, 120.14), LatLng(30.28, 120.17), LatLng(30.26, 120.17), LatLng(30.26, 120.14), ]; bool checkInPolygonArea(LatLng userPoint, List<LatLng> polygon) { int i, j = polygon.length - 1; bool oddNodes = false; for (i = 0; i < polygon.length; i++) { if ((polygon[i].longitude < userPoint.longitude && polygon[j].longitude >= userPoint.longitude || polygon[j].longitude < userPoint.longitude && polygon[i].longitude >= userPoint.longitude) { if (polygon[i].latitude + (userPoint.longitude - polygon[i].longitude) / (polygon[j].longitude - polygon[i].longitude) * (polygon[j].latitude - polygon[i].latitude) < userPoint.latitude) { oddNodes = !oddNodes; } } j = i; } return oddNodes; }
4. 业务跳转逻辑
在应用启动或者需要校验服务权限的前置位置调用校验逻辑:
void checkServiceAvailability() async { Position? userPos = await getUserLocation(); if (userPos == null) { // 自行补充无位置权限的处理逻辑 return; } // 圆形区域判断示例 bool isInServiceArea = checkInCircleArea(userPos); // 多边形区域判断示例 // bool isInServiceArea = checkInPolygonArea(LatLng(userPos.latitude, userPos.longitude), servicePolygon); if (!isInServiceArea) { // 跳转超出服务范围错误页 Navigator.push(context, MaterialPageRoute(builder: (context) => const OutOfServicePage())); } else { // 进入正常服务页面 } }
5. 超出服务范围错误页示例
import 'package:flutter/material.dart'; class OutOfServicePage extends StatelessWidget { const OutOfServicePage({super.key}); @override Widget build(BuildContext context) { return Scaffold( body: Center( child: Column( mainAxisAlignment: MainAxisAlignment.center, children: const [ Icon(Icons.location_off, size: 80, color: Colors.grey), SizedBox(height: 20), Text( '当前地址不在服务范围内', style: TextStyle(fontSize: 18, fontWeight: FontWeight.w500), ), SizedBox(height: 10), Text( '我们暂未开通您所在区域的服务,请稍后再试', style: TextStyle(color: Colors.grey, fontSize: 14), ) ], ), ), ); } }
注意事项
- 若需要校验用户手动输入的地址,需要先将地址通过地理编码转为经纬度坐标后再进行区域判断
- 建议将服务区域的坐标配置存放在服务端,应用启动时拉取最新配置,避免硬编码更新不及时的问题
内容的提问来源于stack exchange,提问作者Shailebhyanand
相关产品推荐
相关产品推荐

