如何在Flutter应用中实现驾车路线展示?可选方案有哪些?
嘿,这个问题我熟!在Flutter里展示驾车路线主要有三种主流方案,每种都有自己的适用场景,下面我给你一步步拆解具体实现和优劣:
这是全球范围内最常用的方案,路线数据精准,功能完善。
实现步骤:
配置依赖与API密钥
首先在pubspec.yaml里添加依赖:dependencies: google_maps_flutter: ^2.5.0 polyline_points: ^1.0.0然后去谷歌云平台申请两个密钥:
Maps SDK for Android/iOS(用于展示地图)和Directions API(用于获取驾车路线数据),分别配置到Android的AndroidManifest.xml和iOS的Info.plist中。初始化地图并绘制路线
先展示基础地图,再调用Directions API获取路线的坐标点,最后用Polyline组件把路线画在地图上。举个简单的例子:import 'dart:convert'; import 'package:google_maps_flutter/google_maps_flutter.dart'; import 'package:http/http.dart' as http; import 'package:polyline_points/polyline_points.dart'; class MapScreen extends StatefulWidget { @override _MapScreenState createState() => _MapScreenState(); } class _MapScreenState extends State<MapScreen> { GoogleMapController? _mapController; final Set<Polyline> _polylines = {}; final LatLng _origin = LatLng(37.7749, -122.4194); // 旧金山 final LatLng _destination = LatLng(34.0522, -118.2437); // 洛杉矶 @override void initState() { super.initState(); _fetchRoute(); } Future<void> _fetchRoute() async { final response = await http.get(Uri.parse( 'https://maps.googleapis.com/maps/api/directions/json?origin=${_origin.latitude},${_origin.longitude}&destination=${_destination.latitude},${_destination.longitude}&key=YOUR_API_KEY' )); if (response.statusCode == 200) { final data = json.decode(response.body); final route = data['routes'][0]['overview_polyline']['points']; final decodedPoints = PolylinePoints().decodePolyline(route); final polylineCoordinates = decodedPoints.map((point) => LatLng(point.latitude, point.longitude)).toList(); setState(() { _polylines.add(Polyline( polylineId: const PolylineId('route'), color: Colors.blueAccent, width: 5, points: polylineCoordinates, )); }); } } @override Widget build(BuildContext context) { return GoogleMap( initialCameraPosition: CameraPosition(target: _origin, zoom: 7), onMapCreated: (controller) => _mapController = controller, polylines: _polylines, markers: { Marker(markerId: const MarkerId('origin'), position: _origin), Marker(markerId: const MarkerId('destination'), position: _destination), }, ); } }
如果你的应用主要面向国内用户,这个方案更靠谱——国内路况适配更好,定位精准,而且免费额度足够大部分中小项目使用。
以高德地图为例:
集成插件与配置密钥
添加依赖:dependencies: amap_flutter_map: ^3.1.0 amap_flutter_base: ^2.1.0 amap_flutter_search: ^3.0.0去高德开发者平台申请API密钥,配置到原生项目中(具体步骤高德官方文档写得很细致)。
调用路线规划API绘制路线
高德插件提供了封装好的路线规划能力,不用自己手动解析坐标:import 'package:amap_flutter_map/amap_flutter_map.dart'; import 'package:amap_flutter_base/amap_flutter_base.dart'; import 'package:amap_flutter_search/amap_flutter_search.dart'; class AMapRouteScreen extends StatefulWidget { @override _AMapRouteScreenState createState() => _AMapRouteScreenState(); } class _AMapRouteScreenState extends State<AMapRouteScreen> { AMapController? _mapController; final RouteSearch _routeSearch = RouteSearch(); @override void initState() { super.initState(); _searchDriveRoute(); } Future<void> _searchDriveRoute() async { final request = DriveRouteSearchRequest( origin: const LatLng(39.908860, 116.397390), // 北京天安门 destination: const LatLng(31.230416, 121.473701), // 上海外滩 ); final result = await _routeSearch.searchDriveRoute(request); if (result.isSuccess && result.route != null) { _mapController?.addRouteOverlay(result.route!); } } @override Widget build(BuildContext context) { return AMapWidget( apiKey: const AMapApiKey(androidKey: 'YOUR_ANDROID_KEY', iosKey: 'YOUR_IOS_KEY'), onMapCreated: (controller) => _mapController = controller, initialCameraPosition: const CameraPosition(target: LatLng(39.908860, 116.397390), zoom: 5), ); } }百度地图的实现逻辑类似,对应的插件是
flutter_bmap,用法大同小异。
如果不想依赖商业SDK,或者需要完全自定义地图样式,这个开源方案是不错的选择——完全免费,自由度高,但路线精度和实时功能不如商业方案。
实现步骤:
集成依赖
dependencies: flutter_map: ^6.1.0 latlong2: ^0.9.0 http: ^0.13.5获取路线并绘制
用OSRM(Open Source Routing Machine)的免费API获取路线,然后在flutter_map上绘制:import 'dart:convert'; import 'package:flutter_map/flutter_map.dart'; import 'package:latlong2/latlong.dart'; import 'package:http/http.dart' as http; class OpenStreetMapRouteScreen extends StatefulWidget { @override _OpenStreetMapRouteScreenState createState() => _OpenStreetMapRouteScreenState(); } class _OpenStreetMapRouteScreenState extends State<OpenStreetMapRouteScreen> { List<LatLng> _routePoints = []; final LatLng _origin = const LatLng(51.5074, -0.1278); // 伦敦 final LatLng _destination = const LatLng(50.8503, -0.1247); // 布莱顿 @override void initState() { super.initState(); _fetchOSRMRoute(); } Future<void> _fetchOSRMRoute() async { final response = await http.get(Uri.parse( 'http://router.project-osrm.org/route/v1/driving/${_origin.longitude},${_origin.latitude};${_destination.longitude},${_destination.latitude}?overview=full&geometries=geojson' )); if (response.statusCode == 200) { final data = json.decode(response.body); final geoJson = data['routes'][0]['geometry']; final coordinates = geoJson['coordinates'] as List; setState(() { _routePoints = coordinates.map((coord) => LatLng(coord[1], coord[0])).toList(); }); } } @override Widget build(BuildContext context) { return FlutterMap( options: MapOptions( center: _origin, zoom: 8, ), children: [ TileLayer( urlTemplate: 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', subdomains: const ['a', 'b', 'c'], ), PolylineLayer( polylines: [ Polyline( points: _routePoints, strokeWidth: 4, color: Colors.redAccent, ), ], ), MarkerLayer( markers: [ Marker( point: _origin, width: 80, height: 80, child: const Icon(Icons.location_on, color: Colors.green, size: 40), ), Marker( point: _destination, width: 80, height: 80, child: const Icon(Icons.location_on, color: Colors.red, size: 40), ), ], ), ], ); } }
- 谷歌地图:全球覆盖完善,API生态成熟,但国内访问受限,超出免费额度后需付费。
- 国内SDK(高德/百度):国内路况适配极佳,定位精准,免费额度充足,适合国内用户。
- 开源方案:完全免费,自定义性强,但路线精度、实时路况等功能弱于商业SDK,适合小项目或非核心地图功能。
内容的提问来源于stack exchange,提问作者user1261913

