init project

This commit is contained in:
Kuloud
2023-12-22 21:23:24 +08:00
commit 1fb3d91106
461 changed files with 58770 additions and 0 deletions

419
lib/src/amap_widget.dart Normal file
View File

@ -0,0 +1,419 @@
part of amap_map;
typedef void MapCreatedCallback(AMapController controller);
///用于展示高德地图的Widget
class AMapWidget extends StatefulWidget {
///高德开放平台的key
///
final AMapApiKey? apiKey;
/// 初始化时的地图中心点
final CameraPosition initialCameraPosition;
///地图类型
final MapType mapType;
///自定义地图样式
final CustomStyleOptions? customStyleOptions;
///定位小蓝点
final MyLocationStyleOptions? myLocationStyleOptions;
///缩放级别范围
final MinMaxZoomPreference? minMaxZoomPreference;
///地图显示范围
final LatLngBounds? limitBounds;
///显示路况开关
final bool trafficEnabled;
/// 地图poi是否允许点击
final bool touchPoiEnabled;
///是否显示3D建筑物
final bool buildingsEnabled;
///是否显示底图文字标注
final bool labelsEnabled;
///是否显示指南针
final bool compassEnabled;
///是否显示比例尺
final bool scaleEnabled;
///是否支持缩放手势
final bool zoomGesturesEnabled;
///是否支持滑动手势
final bool scrollGesturesEnabled;
///是否支持旋转手势
final bool rotateGesturesEnabled;
///是否支持倾斜手势
final bool tiltGesturesEnabled;
/// 地图上显示的Marker
final Set<Marker> markers;
/// 地图上显示的polyline
final Set<Polyline> polylines;
/// 地图上显示的polygon
final Set<Polygon> polygons;
/// 地图创建成功的回调, 收到此回调之后才可以操作地图
final MapCreatedCallback? onMapCreated;
/// 相机视角持续移动的回调
final ArgumentCallback<CameraPosition>? onCameraMove;
/// 相机视角移动结束的回调
final ArgumentCallback<CameraPosition>? onCameraMoveEnd;
/// 地图单击事件的回调
final ArgumentCallback<LatLng>? onTap;
/// 地图长按事件的回调
final ArgumentCallback<LatLng>? onLongPress;
/// 地图POI的点击回调需要`touchPoiEnabled`true才能回调
final ArgumentCallback<AMapPoi>? onPoiTouched;
///位置回调
final ArgumentCallback<AMapLocation>? onLocationChanged;
///需要应用到地图上的手势集合
final Set<Factory<OneSequenceGestureRecognizer>> gestureRecognizers;
///高德合规声明配置
///
/// 高德SDK合规使用方案请参考https://lbs.amap.com/news/sdkhgsy
final AMapPrivacyStatement? privacyStatement;
/// 创建一个展示高德地图的widget
///
/// 如果使用的高德地图SDK的版本是8.1.0及以上版本,
/// 在app首次启动时必须传入高德合规声明配置[privacyStatement],后续如果没有变化不需要重复设置
/// <li>[privacyStatement.hasContains] 隐私权政策是否包含高德开平隐私权政策</li>
/// <li>[privacyStatement.hasShow] 是否已经弹窗展示给用户</li>
/// <li>[privacyStatement.hasAgree] 隐私权政策是否已经取得用户同意</li>
/// 以上三个值任何一个为false都会造成地图插件不工作白屏情况
///
/// 高德SDK合规使用方案请参考https://lbs.amap.com/news/sdkhgsy
///
/// [AssertionError] will be thrown if [initialCameraPosition] is null;
const AMapWidget({
Key? key,
this.privacyStatement,
this.apiKey,
this.initialCameraPosition =
const CameraPosition(target: LatLng(39.909187, 116.397451), zoom: 10),
this.mapType = MapType.normal,
this.buildingsEnabled = true,
this.compassEnabled = false,
this.labelsEnabled = true,
this.limitBounds,
this.minMaxZoomPreference,
this.rotateGesturesEnabled = true,
this.scaleEnabled = true,
this.scrollGesturesEnabled = true,
this.tiltGesturesEnabled = true,
this.touchPoiEnabled = true,
this.trafficEnabled = false,
this.zoomGesturesEnabled = true,
this.onMapCreated,
this.gestureRecognizers = const <Factory<OneSequenceGestureRecognizer>>{},
this.customStyleOptions,
this.myLocationStyleOptions,
this.onCameraMove,
this.onCameraMoveEnd,
this.onLocationChanged,
this.onTap,
this.onLongPress,
this.onPoiTouched,
this.markers = const <Marker>{},
this.polylines = const <Polyline>{},
this.polygons = const <Polygon>{},
}) : super(key: key);
///
@override
State<StatefulWidget> createState() => _MapState();
}
class _MapState extends State<AMapWidget> {
Map<String, Marker> _markers = <String, Marker>{};
Map<String, Polyline> _polylines = <String, Polyline>{};
Map<String, Polygon> _polygons = <String, Polygon>{};
final Completer<AMapController> _controller = Completer<AMapController>();
late _AMapOptions _mapOptions;
@override
Widget build(BuildContext context) {
AMapUtil.init(context);
final Map<String, dynamic> creationParams = <String, dynamic>{
'privacyStatement': widget.privacyStatement?.toMap(),
'apiKey': widget.apiKey?.toMap(),
'initialCameraPosition': widget.initialCameraPosition.toMap(),
'options': _mapOptions.toMap(),
'markersToAdd': serializeOverlaySet(widget.markers),
'polylinesToAdd': serializeOverlaySet(widget.polylines),
'polygonsToAdd': serializeOverlaySet(widget.polygons),
};
Widget mapView = _methodChannel.buildView(
creationParams,
widget.gestureRecognizers,
onPlatformViewCreated,
);
return mapView;
}
@override
void initState() {
super.initState();
_mapOptions = _AMapOptions.fromWidget(widget);
_markers = keyByMarkerId(widget.markers);
_polygons = keyByPolygonId(widget.polygons);
_polylines = keyByPolylineId(widget.polylines);
print('initState AMapWidget');
}
@override
void dispose() async {
super.dispose();
AMapController controller = await _controller.future;
controller.disponse();
print('dispose AMapWidget with mapId: ${controller.mapId}');
}
@override
void reassemble() {
super.reassemble();
print('reassemble AMapWidget');
}
@override
void deactivate() async {
super.deactivate();
print('deactivate AMapWidget}');
}
@override
void didUpdateWidget(covariant AMapWidget oldWidget) {
super.didUpdateWidget(oldWidget);
_updateOptions();
_updateMarkers();
_updatePolylines();
_updatePolygons();
}
Future<void> onPlatformViewCreated(int id) async {
final AMapController controller = await AMapController.init(
id,
widget.initialCameraPosition,
this,
);
_controller.complete(controller);
final MapCreatedCallback? _onMapCreated = widget.onMapCreated;
if (_onMapCreated != null) {
_onMapCreated(controller);
}
}
void onMarkerTap(String markerId) {
final Marker? _marker = _markers[markerId];
if (_marker != null) {
final ArgumentCallback<String>? _onTap = _marker.onTap;
if (_onTap != null) {
_onTap(markerId);
}
}
}
void onMarkerDragEnd(String markerId, LatLng position) {
final Marker? _marker = _markers[markerId];
if (_marker != null) {
final MarkerDragEndCallback? _onDragEnd = _marker.onDragEnd;
if (_onDragEnd != null) {
_onDragEnd(markerId, position);
}
}
}
void onPolylineTap(String polylineId) {
final Polyline? _polyline = _polylines[polylineId];
if (_polyline != null) {
final ArgumentCallback<String>? _onTap = _polyline.onTap;
if (_onTap != null) {
_onTap(polylineId);
}
}
}
void _updateOptions() async {
final _AMapOptions newOptions = _AMapOptions.fromWidget(widget);
final Map<String, dynamic> updates = _mapOptions._updatesMap(newOptions);
if (updates.isEmpty) {
return;
}
final AMapController controller = await _controller.future;
// ignore: unawaited_futures
controller._updateMapOptions(updates);
_mapOptions = newOptions;
}
void _updateMarkers() async {
final AMapController controller = await _controller.future;
// ignore: unawaited_futures
controller._updateMarkers(
MarkerUpdates.from(_markers.values.toSet(), widget.markers));
_markers = keyByMarkerId(widget.markers);
}
void _updatePolylines() async {
final AMapController controller = await _controller.future;
controller._updatePolylines(
PolylineUpdates.from(_polylines.values.toSet(), widget.polylines));
_polylines = keyByPolylineId(widget.polylines);
}
void _updatePolygons() async {
final AMapController controller = await _controller.future;
controller._updatePolygons(
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons));
_polygons = keyByPolygonId(widget.polygons);
}
}
//高德地图参数设置
class _AMapOptions {
///地图类型
final MapType mapType;
///自定义地图样式
final CustomStyleOptions? customStyleOptions;
///定位小蓝点
final MyLocationStyleOptions? myLocationStyleOptions;
//缩放级别范围
final MinMaxZoomPreference? minMaxZoomPreference;
///地图显示范围
final LatLngBounds? limitBounds;
///显示路况开关
final bool? trafficEnabled;
/// 地图poi是否允许点击
final bool? touchPoiEnabled;
///是否显示3D建筑物
final bool? buildingsEnabled;
///是否显示底图文字标注
final bool? labelsEnabled;
///是否显示指南针
final bool? compassEnabled;
///是否显示比例尺
final bool? scaleEnabled;
///是否支持缩放手势
final bool? zoomGesturesEnabled;
///是否支持滑动手势
final bool? scrollGesturesEnabled;
///是否支持旋转手势
final bool? rotateGesturesEnabled;
///是否支持仰角手势
final bool? tiltGesturesEnabled;
_AMapOptions({
this.mapType = MapType.normal,
this.buildingsEnabled,
this.customStyleOptions,
this.myLocationStyleOptions,
this.compassEnabled,
this.labelsEnabled,
this.limitBounds,
this.minMaxZoomPreference,
this.scaleEnabled,
this.touchPoiEnabled,
this.trafficEnabled,
this.rotateGesturesEnabled,
this.scrollGesturesEnabled,
this.tiltGesturesEnabled,
this.zoomGesturesEnabled,
});
static _AMapOptions fromWidget(AMapWidget map) {
return _AMapOptions(
mapType: map.mapType,
buildingsEnabled: map.buildingsEnabled,
compassEnabled: map.compassEnabled,
labelsEnabled: map.labelsEnabled,
limitBounds: map.limitBounds,
minMaxZoomPreference: map.minMaxZoomPreference,
scaleEnabled: map.scaleEnabled,
touchPoiEnabled: map.touchPoiEnabled,
trafficEnabled: map.trafficEnabled,
rotateGesturesEnabled: map.rotateGesturesEnabled,
scrollGesturesEnabled: map.scrollGesturesEnabled,
tiltGesturesEnabled: map.tiltGesturesEnabled,
zoomGesturesEnabled: map.zoomGesturesEnabled,
customStyleOptions: map.customStyleOptions?.clone(),
myLocationStyleOptions: map.myLocationStyleOptions?.clone(),
);
}
Map<String, dynamic> toMap() {
final Map<String, dynamic> optionsMap = <String, dynamic>{};
void addIfNonNull(String fieldName, dynamic value) {
if (value != null) {
optionsMap[fieldName] = value;
}
}
addIfNonNull('mapType', mapType.index);
addIfNonNull('buildingsEnabled', buildingsEnabled);
addIfNonNull('customStyleOptions', customStyleOptions?.clone().toMap());
addIfNonNull('compassEnabled', compassEnabled);
addIfNonNull('labelsEnabled', labelsEnabled);
addIfNonNull('limitBounds', limitBounds?.toJson());
addIfNonNull('minMaxZoomPreference', minMaxZoomPreference?.toJson());
addIfNonNull('scaleEnabled', scaleEnabled);
addIfNonNull('touchPoiEnabled', touchPoiEnabled);
addIfNonNull('trafficEnabled', trafficEnabled);
addIfNonNull('rotateGesturesEnabled', rotateGesturesEnabled);
addIfNonNull('scrollGesturesEnabled', scrollGesturesEnabled);
addIfNonNull('tiltGesturesEnabled', tiltGesturesEnabled);
addIfNonNull('zoomGesturesEnabled', zoomGesturesEnabled);
addIfNonNull('myLocationStyle', myLocationStyleOptions?.clone().toMap());
return optionsMap;
}
Map<String, dynamic> _updatesMap(_AMapOptions newOptions) {
final Map<String, dynamic> prevOptionsMap = toMap();
return newOptions.toMap()
..removeWhere((String key, dynamic value) =>
(_checkChange(key, prevOptionsMap[key], value)));
}
bool _checkChange(String key, dynamic preValue, dynamic newValue) {
if (key == 'myLocationStyle' || key == 'customStyleOptions') {
return preValue?.toString() == newValue?.toString();
} else {
return preValue == newValue;
}
}
}