我来详细介绍 Flutter 中常用的 Google 地图组件包 google_maps_flutter。
概述
google_maps_flutter 是 Flutter 官方维护的 Google Maps 插件,允许在 Flutter 应用中嵌入 Google 地图。
安装配置
1. 添加依赖
yaml
dependencies:
google_maps_flutter: ^2.4.0
2. 平台配置
Android:
xml
<!-- android/app/src/main/AndroidManifest.xml -->
<manifest>
<application>
<meta-data
android:name="com.google.android.geo.API_KEY"
android:value="YOUR_ANDROID_API_KEY"/>
</application>
</manifest>
iOS:
swift
// ios/Runner/AppDelegate.swift
import GoogleMaps
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GMSServices.provideAPIKey("YOUR_IOS_API_KEY")
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
}
基础用法
1. 显示地图
dart
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class SimpleMap extends StatefulWidget {
@override
_SimpleMapState createState() => _SimpleMapState();
}
class _SimpleMapState extends State<SimpleMap> {
late GoogleMapController mapController;
final LatLng _center = const LatLng(31.2304, 121.4737); // 上海坐标
void _onMapCreated(GoogleMapController controller) {
mapController = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: Text('Google Maps')),
body: GoogleMap(
onMapCreated: _onMapCreated,
initialCameraPosition: CameraPosition(
target: _center,
zoom: 12.0,
),
// 启用用户位置
myLocationEnabled: true,
myLocationButtonEnabled: true,
// 手势支持
zoomControlsEnabled: true,
rotateGesturesEnabled: true,
scrollGesturesEnabled: true,
tiltGesturesEnabled: true,
zoomGesturesEnabled: true,
),
);
}
}
2. 添加标记
dart
Set<Marker> _markers = {};
@override
void initState() {
super.initState();
// 添加标记
_markers.add(
Marker(
markerId: MarkerId('marker_1'),
position: LatLng(31.2304, 121.4737),
infoWindow: InfoWindow(
title: '上海',
snippet: '中国最大城市',
),
icon: BitmapDescriptor.defaultMarkerWithHue(
BitmapDescriptor.hueRed,
),
onTap: () {
print('标记被点击');
},
),
);
// 添加自定义图标标记
_markers.add(
Marker(
markerId: MarkerId('custom_marker'),
position: LatLng(31.2204, 121.4837),
icon: BitmapDescriptor.fromBytes(customIconBytes),
anchor: Offset(0.5, 0.5), // 图标锚点
),
);
}
GoogleMap(
markers: _markers,
// ... 其他配置
)
3. 绘制图形
dart
Set<Polygon> _polygons = {};
Set<Polyline> _polylines = {};
Set<Circle> _circles = {};
void _addShapes() {
// 多边形
_polygons.add(
Polygon(
polygonId: PolygonId('polygon_1'),
points: [
LatLng(31.2304, 121.4737),
LatLng(31.2404, 121.4837),
LatLng(31.2204, 121.4937),
],
strokeWidth: 2,
strokeColor: Colors.blue,
fillColor: Colors.blue.withOpacity(0.15),
),
);
// 折线
_polylines.add(
Polyline(
polylineId: PolylineId('polyline_1'),
points: [
LatLng(31.2304, 121.4737),
LatLng(31.2404, 121.4837),
],
color: Colors.red,
width: 3,
geodesic: true, // 大圆线
),
);
// 圆形
_circles.add(
Circle(
circleId: CircleId('circle_1'),
center: LatLng(31.2304, 121.4737),
radius: 500, // 米
strokeWidth: 2,
strokeColor: Colors.green,
fillColor: Colors.green.withOpacity(0.15),
),
);
}
GoogleMap(
polygons: _polygons,
polylines: _polylines,
circles: _circles,
)
4. 地图控制
dart
// 移动到指定位置
void _moveCamera() {
mapController.animateCamera(
CameraUpdate.newCameraPosition(
CameraPosition(
target: LatLng(39.9042, 116.4074), // 北京
zoom: 14.0,
bearing: 45, // 旋转角度
tilt: 30,// 倾斜角度
),
),
);
}
// 移动到边界
void _moveToBounds() {
mapController.animateCamera(
CameraUpdate.newLatLngBounds(
LatLngBounds(
southwest: LatLng(31.2204, 121.4637),
northeast: LatLng(31.2404, 121.4837),
),
padding: 50, // 边距
),
);
}
// 获取当前可视区域
void _getVisibleRegion() async {
LatLngBounds bounds = await mapController.getVisibleRegion();
print('可视区域: ${bounds.southwest} - ${bounds.northeast}');
}
5. 事件监听
dart
GoogleMap(
onMapCreated: (controller) {
mapController = controller;
},
onCameraMove: (CameraPosition position) {
print('相机移动: ${position.target}');
},
onCameraIdle: () {
print('相机停止移动');
},
onTap: (LatLng position) {
print('地图点击: $position');
},
onLongPress: (LatLng position) {
print('地图长按: $position');
},
)
6. 自定义地图样式
dart
void _setMapStyle() async {
String style = await DefaultAssetBundle.of(context)
.loadString('assets/map_style.json');
mapController.setMapStyle(style);
}
// map_style.json 示例
[
{
"featureType": "all",
"elementType": "geometry",
"stylers": [
{"color": "#242f3e"}
]
},
{
"featureType": "water",
"elementType": "labels.text.fill",
"stylers": [
{"color": "#515c6d"}
]
}
]
高级功能
1. 标记聚类
使用第三方库 flutter_map_marker_cluster:
dart
dependencies:
flutter_map_marker_cluster: ^0.3.0
2. 离线地图
dart
// 设置离线区域
void _setOfflineRegion() {
mapController.setOfflineTileData(
LatLngBounds(
southwest: LatLng(31.2204, 121.4637),
northeast: LatLng(31.2404, 121.4837),
),
minZoom: 10,
maxZoom: 15,
);
}
3. 性能优化
dart
class OptimizedMap extends StatelessWidget {
@override
Widget build(BuildContext context) {
return GoogleMap(
initialCameraPosition: CameraPosition(
target: LatLng(31.2304, 121.4737),
zoom: 12,
),
// 优化选项
minMaxZoomPreference: MinMaxZoomPreference(8, 18),
cameraTargetBounds: CameraTargetBounds.unbounded,
// 轻量模式
liteModeEnabled: false,
// 纹理层
textureRenderingEnabled: false,
// 标记批处理
markersClusteringEnabled: true,
);
}
}
完整示例
dart
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
class AdvancedMapPage extends StatefulWidget {
@override
_AdvancedMapPageState createState() => _AdvancedMapPageState();
}
class _AdvancedMapPageState extends State<AdvancedMapPage> {
late GoogleMapController _controller;
Set<Marker> _markers = {};
Set<Polyline> _polylines = {};
final LatLng _initialPosition = LatLng(31.2304, 121.4737);
@override
void initState() {
super.initState();
_setupMarkers();
_setupPolylines();
}
void _setupMarkers() {
_markers.addAll([
Marker(
markerId: MarkerId('marker1'),
position: LatLng(31.2304, 121.4737),
infoWindow: InfoWindow(title: '位置1'),
),
Marker(
markerId: MarkerId('marker2'),
position: LatLng(31.2404, 121.4837),
infoWindow: InfoWindow(title: '位置2'),
),
]);
}
void _setupPolylines() {
_polylines.add(
Polyline(
polylineId: PolylineId('route'),
points: [
LatLng(31.2304, 121.4737),
LatLng(31.2404, 121.4837),
],
color: Colors.blue,
width: 4,
),
);
}
void _zoomIn() {
_controller.animateCamera(CameraUpdate.zoomIn());
}
void _zoomOut() {
_controller.animateCamera(CameraUpdate.zoomOut());
}
void _goToMyLocation() async {
// 实际应用中需要获取用户当前位置
_controller.animateCamera(
CameraUpdate.newLatLng(_initialPosition),
);
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('高级地图示例'),
actions: [
IconButton(
icon: Icon(Icons.my_location),
onPressed: _goToMyLocation,
),
],
),
body: Stack(
children: [
GoogleMap(
onMapCreated: (controller) => _controller = controller,
initialCameraPosition: CameraPosition(
target: _initialPosition,
zoom: 12,
),
markers: _markers,
polylines: _polylines,
myLocationEnabled: true,
myLocationButtonEnabled: false,
zoomControlsEnabled: false,
),
Positioned(
right: 16,
bottom: 100,
child: Column(
children: [
FloatingActionButton(
onPressed: _zoomIn,
child: Icon(Icons.add),
mini: true,
),
SizedBox(height: 8),
FloatingActionButton(
onPressed: _zoomOut,
child: Icon(Icons.remove),
mini: true,
),
],
),
),
],
),
);
}
}
注意事项
- API 密钥安全:不要将 API 密钥硬编码在代码中
- 计费:Google Maps 有使用限制和计费标准
- 权限:确保在 Android 和 iOS 中正确配置位置权限
- 网络:地图需要网络连接加载图块
- 性能:大量标记或复杂图形可能影响性能
替代方案
如果 Google Maps 不可用,可以考虑:
mapbox_gl:Mapbox 地图leaflet_flutter:Leaflet 地图amap_flutter_map:高德地图(中国)
这个插件提供了丰富的功能,适合大多数地图应用需求。记得根据实际功能选择合适的配置,并注意平台特定的设置。