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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 12:33:02