release 1.0.4
This commit is contained in:
@ -1,12 +1,12 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
// Copyright 2020 lbs.amap.com
|
||||
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
@ -48,48 +48,52 @@ class AMapController {
|
||||
}
|
||||
|
||||
void _connectStreams(int mapId) {
|
||||
if (_mapState.widget.onLocationChanged != null) {
|
||||
_methodChannel.onLocationChanged(mapId: mapId).listen(
|
||||
(LocationChangedEvent e) =>
|
||||
_mapState.widget.onLocationChanged!(e.value));
|
||||
}
|
||||
|
||||
if (_mapState.widget.onCameraMove != null) {
|
||||
_methodChannel.onCameraMove(mapId: mapId).listen(
|
||||
(CameraPositionMoveEvent e) =>
|
||||
_mapState.widget.onCameraMove!(e.value));
|
||||
}
|
||||
if (_mapState.widget.onCameraMoveEnd != null) {
|
||||
_methodChannel.onCameraMoveEnd(mapId: mapId).listen(
|
||||
(CameraPositionMoveEndEvent e) =>
|
||||
_mapState.widget.onCameraMoveEnd!(e.value));
|
||||
}
|
||||
if (_mapState.widget.onTap != null) {
|
||||
_methodChannel
|
||||
.onMapTap(mapId: mapId)
|
||||
.listen(((MapTapEvent e) => _mapState.widget.onTap!(e.value)));
|
||||
}
|
||||
if (_mapState.widget.onLongPress != null) {
|
||||
_methodChannel.onMapLongPress(mapId: mapId).listen(
|
||||
((MapLongPressEvent e) => _mapState.widget.onLongPress!(e.value)));
|
||||
}
|
||||
|
||||
if (_mapState.widget.onPoiTouched != null) {
|
||||
_methodChannel.onPoiTouched(mapId: mapId).listen(
|
||||
((MapPoiTouchEvent e) => _mapState.widget.onPoiTouched!(e.value)));
|
||||
}
|
||||
_methodChannel.onLocationChanged(mapId: mapId).listen(
|
||||
(LocationChangedEvent e) =>
|
||||
_mapState.widget.onLocationChanged?.call(e.value));
|
||||
|
||||
_methodChannel
|
||||
.onMarkerTap(mapId: mapId)
|
||||
.listen((MarkerTapEvent e) => _mapState.onMarkerTap(e.value));
|
||||
|
||||
_methodChannel.onMarkerDragEnd(mapId: mapId).listen(
|
||||
(MarkerDragEndEvent e) =>
|
||||
_mapState.onMarkerDragEnd(e.value, e.position));
|
||||
.onCameraMove(mapId: mapId)
|
||||
.listen((CameraPositionMoveEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onCameraMove(e.value));
|
||||
_mapState.widget.onCameraMove?.call(e.value);
|
||||
});
|
||||
|
||||
_methodChannel
|
||||
.onPolylineTap(mapId: mapId)
|
||||
.listen((PolylineTapEvent e) => _mapState.onPolylineTap(e.value));
|
||||
.onCameraMoveEnd(mapId: mapId)
|
||||
.listen((CameraPositionMoveEndEvent e) {
|
||||
_mapState._extensions.values
|
||||
.forEach((ext) => ext.onCameraMoveEnd(e.value));
|
||||
_mapState.widget.onCameraMoveEnd?.call(e.value);
|
||||
});
|
||||
_methodChannel
|
||||
.onMapTap(mapId: mapId)
|
||||
.listen(((MapTapEvent e) => _mapState.widget.onTap?.call(e.value)));
|
||||
_methodChannel.onMapLongPress(mapId: mapId).listen(((MapLongPressEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onLongPress(e.value));
|
||||
_mapState.widget.onLongPress?.call(e.value);
|
||||
}));
|
||||
|
||||
_methodChannel.onPoiTouched(mapId: mapId).listen(((MapPoiTouchEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onPoiTouched(e.value));
|
||||
_mapState.widget.onPoiTouched?.call(e.value);
|
||||
}));
|
||||
|
||||
_methodChannel.onMarkerTap(mapId: mapId).listen((MarkerTapEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onMarkerTap(e.value));
|
||||
_mapState.onMarkerTap(e.value);
|
||||
});
|
||||
|
||||
_methodChannel.onMarkerDragEnd(mapId: mapId).listen((MarkerDragEndEvent e) {
|
||||
_mapState._extensions.values
|
||||
.forEach((ext) => ext.onMarkerDragEnd(e.value));
|
||||
_mapState.onMarkerDragEnd(e.value, e.position);
|
||||
});
|
||||
|
||||
_methodChannel.onPolylineTap(mapId: mapId).listen((PolylineTapEvent e) {
|
||||
_mapState._extensions.values.forEach((ext) => ext.onPolylineTap(e.value));
|
||||
_mapState.onPolylineTap(e.value);
|
||||
});
|
||||
}
|
||||
|
||||
void disponse() {
|
||||
@ -137,12 +141,12 @@ class AMapController {
|
||||
return _methodChannel.clearDisk(mapId: mapId);
|
||||
}
|
||||
|
||||
/// 经纬度转屏幕坐标
|
||||
/// 经纬度转屏幕坐标 since v1.0.3
|
||||
Future<ScreenCoordinate> toScreenCoordinate(LatLng latLng) {
|
||||
return _methodChannel.toScreenLocation(latLng, mapId: mapId);
|
||||
}
|
||||
|
||||
/// 屏幕坐标转经纬度
|
||||
/// 屏幕坐标转经纬度 From v1.0.3
|
||||
Future<LatLng> fromScreenCoordinate(ScreenCoordinate screenCoordinate) {
|
||||
return _methodChannel.fromScreenLocation(screenCoordinate, mapId: mapId);
|
||||
}
|
||||
|
@ -1,11 +1,11 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@ -20,7 +20,12 @@ class AMapInitializer {
|
||||
|
||||
AMapInitializer._();
|
||||
|
||||
static Future<void> init(BuildContext context, AMapApiKey apiKey) async {
|
||||
/// 初始化地图组件
|
||||
///
|
||||
/// @param context 用于图片资源适配屏幕密度,需在[AMapWidget]使用前调用[init]方法
|
||||
/// @param apiKey 申请的 AMapSDK Key,如果熟悉原生侧集成配置,可以参考高德文档集成,可选
|
||||
///
|
||||
static void init(BuildContext context, {AMapApiKey? apiKey}) {
|
||||
AMapUtil.init(context);
|
||||
_apiKey = apiKey;
|
||||
}
|
||||
@ -33,7 +38,7 @@ class AMapInitializer {
|
||||
///
|
||||
/// 高德SDK合规使用方案请参考:https://lbs.amap.com/news/sdkhgsy
|
||||
///
|
||||
static updatePrivacyAgree(AMapPrivacyStatement privacyStatement) {
|
||||
static void updatePrivacyAgree(AMapPrivacyStatement privacyStatement) {
|
||||
_privacyStatement = privacyStatement;
|
||||
}
|
||||
}
|
||||
|
@ -1,16 +1,17 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
part of amap_map;
|
||||
|
||||
/// 加载器,在[AMapWidget]的生命周期上绑定拓展
|
||||
class AMapLoader extends StatefulWidget {
|
||||
const AMapLoader(
|
||||
{super.key, required this.mapView, required this.extensions});
|
||||
@ -22,19 +23,32 @@ class AMapLoader extends StatefulWidget {
|
||||
State<AMapLoader> createState() => _AMapLoaderState();
|
||||
|
||||
static void prepare() {
|
||||
// TODO loop handle with extensions
|
||||
// TODO Loader 初始化静态方法,在initState时做些逻辑
|
||||
}
|
||||
|
||||
/// 传递构建视图,拓展按需进行包装和挂载定制视图
|
||||
Widget buildFromExtension(AMapContext aMapContext) {
|
||||
// TODO loop handle with extensions
|
||||
return mapView;
|
||||
Widget child = mapView;
|
||||
for (var e in extensions) {
|
||||
child = e.build(aMapContext, child);
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/// [didChangeDependencies] 状态更新时,挨个遍历进行拓展的更新操作
|
||||
void prepareFromExtension(AMapContext aMapContext) {
|
||||
for (var e in extensions) {
|
||||
e.prepare(aMapContext);
|
||||
}
|
||||
}
|
||||
|
||||
/// [didChangeDependencies] 状态更新时,挨个遍历进行拓展的更新操作
|
||||
void updateFromExtension(AMapContext aMapContext) {
|
||||
for (var e in extensions) {
|
||||
e.update(aMapContext);
|
||||
}
|
||||
// Future.forEach(extensions, (ext) => ext.update(aMapContext));
|
||||
}
|
||||
}
|
||||
|
||||
class _AMapLoaderState extends State<AMapLoader> {
|
||||
@ -48,6 +62,16 @@ class _AMapLoaderState extends State<AMapLoader> {
|
||||
super.didChangeDependencies();
|
||||
}
|
||||
|
||||
@override
|
||||
void didUpdateWidget(covariant AMapLoader oldWidget) {
|
||||
final aMapContext = AMapContext(
|
||||
buildContext: context,
|
||||
currentStep: CurrentStep.updating,
|
||||
loader: widget);
|
||||
widget.updateFromExtension(aMapContext);
|
||||
super.didUpdateWidget(oldWidget);
|
||||
}
|
||||
|
||||
@override
|
||||
void dispose() {
|
||||
for (var e in widget.extensions) {
|
||||
|
@ -220,6 +220,7 @@ class _MapState extends State<AMapWidget> {
|
||||
_updateMarkers();
|
||||
_updatePolylines();
|
||||
_updatePolygons();
|
||||
_updateExtensions();
|
||||
}
|
||||
|
||||
Future<void> onPlatformViewCreated(int id) async {
|
||||
@ -231,8 +232,12 @@ class _MapState extends State<AMapWidget> {
|
||||
_controller.complete(controller);
|
||||
|
||||
if (_extensions.isNotEmpty) {
|
||||
await Future.forEach(
|
||||
_extensions.values, (e) => e.bindMethodChannel(controller.channel));
|
||||
debugPrint('[onPlatformViewCreated] $controller');
|
||||
await Future.forEach(_extensions.values, (e) {
|
||||
debugPrint('[onPlatformViewCreated] controller: ${controller.mapId}');
|
||||
e.bindMethodChannel(controller.channel);
|
||||
e.bindMapController(controller);
|
||||
});
|
||||
}
|
||||
|
||||
final MapCreatedCallback? _onMapCreated = widget.onMapCreated;
|
||||
@ -304,6 +309,11 @@ class _MapState extends State<AMapWidget> {
|
||||
PolygonUpdates.from(_polygons.values.toSet(), widget.polygons));
|
||||
_polygons = keyByPolygonId(widget.polygons);
|
||||
}
|
||||
|
||||
void _updateExtensions() async {
|
||||
// final AMapController controller = await _controller.future;
|
||||
_extensions = keyByExtensionId(widget.extensions);
|
||||
}
|
||||
}
|
||||
|
||||
//高德地图参数设置
|
||||
|
121
lib/src/extension/buildin/info_window_extension.dart
Normal file
121
lib/src/extension/buildin/info_window_extension.dart
Normal file
@ -0,0 +1,121 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
/// [amap_map]插件支持默认的[InfoWindow]展示[title]和[snippet]字段,如果要自定义
|
||||
/// [InfoWindow],需要集成此内置插件。
|
||||
///
|
||||
/// ```dart
|
||||
/// AMapWidget map = AMapWidget(
|
||||
/// onMapCreated: _onMapCreated,
|
||||
/// markers: Set<Marker>.of(_markers.values),
|
||||
/// extensions: [
|
||||
/// InfoWindowExtension(
|
||||
/// infoWindow: Container(
|
||||
/// child: Text('Custom widget'),
|
||||
/// ))
|
||||
/// ],
|
||||
/// )
|
||||
/// ```
|
||||
///
|
||||
/// 此插件会在[AMapWidget]外侧套一层[Stack],根据屏幕坐标和经纬度进行适配自定义视图
|
||||
///
|
||||
/// ```dart
|
||||
/// Stack(
|
||||
/// children: [
|
||||
/// child,
|
||||
/// Positioned(
|
||||
/// top: 0,
|
||||
/// left: 0,
|
||||
/// child: Visibility(child: infoWindow),
|
||||
/// ),
|
||||
/// ],
|
||||
/// )
|
||||
/// ```
|
||||
class InfoWindowExtension extends AMapExtension {
|
||||
InfoWindowExtension({required this.infoWindow, this.option});
|
||||
|
||||
StreamController<InfoWindowExtension> _streamController =
|
||||
StreamController<InfoWindowExtension>.broadcast();
|
||||
|
||||
final Widget infoWindow;
|
||||
InfoWindowOption? option;
|
||||
|
||||
AMapController? mapController;
|
||||
double? _x;
|
||||
double? _y;
|
||||
|
||||
@override
|
||||
void update(AMapContext aMapContext) {
|
||||
_update();
|
||||
}
|
||||
|
||||
@override
|
||||
onCameraMove(CameraPosition value) {
|
||||
_update();
|
||||
}
|
||||
|
||||
_update() async {
|
||||
if (mapController == null || option?.latLng == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
final coordinate = await mapController!.toScreenCoordinate(option!.latLng!);
|
||||
|
||||
_x = coordinate.x.toDouble();
|
||||
_y = coordinate.y.toDouble();
|
||||
|
||||
_streamController.add(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bindMapController(AMapController controller) {
|
||||
debugPrint('[InfoWindowExtension] bindMapController: $controller');
|
||||
mapController = controller;
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(AMapContext aMapContext, Widget child) {
|
||||
return Stack(
|
||||
children: [
|
||||
child,
|
||||
StreamBuilder<InfoWindowExtension>(
|
||||
key: ValueKey(this),
|
||||
initialData: this,
|
||||
stream: _streamController.stream,
|
||||
builder: (context, snapshot) {
|
||||
final data = snapshot.data;
|
||||
if (data == null ||
|
||||
!(data.option?.show ?? false) ||
|
||||
data._x == null) {
|
||||
return Container();
|
||||
}
|
||||
|
||||
return Positioned(
|
||||
top: data._y,
|
||||
left: data._x,
|
||||
child: Container(
|
||||
margin: data.option?.offset,
|
||||
child: infoWindow,
|
||||
),
|
||||
);
|
||||
}),
|
||||
],
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class InfoWindowOption {
|
||||
bool show = false;
|
||||
LatLng? latLng;
|
||||
EdgeInsetsGeometry? offset;
|
||||
|
||||
InfoWindowOption({this.show = false, this.latLng, this.offset});
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'InfoWindowOption{show: $show, latLng: $latLng, offset: $offset}';
|
||||
}
|
||||
}
|
1
lib/src/extension/extensions.dart
Normal file
1
lib/src/extension/extensions.dart
Normal file
@ -0,0 +1 @@
|
||||
export 'buildin/info_window_extension.dart';
|
@ -1,7 +1,21 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
|
||||
import 'types.dart';
|
||||
|
||||
/// 插件拓展,绑定[AMapWidget]的生命周期和控制器,实现基于地图的拓展能力(通常是地图交互的可
|
||||
/// 选功能)
|
||||
abstract class AMapExtension {
|
||||
late String _id;
|
||||
|
||||
@ -11,11 +25,48 @@ abstract class AMapExtension {
|
||||
this._id = this.hashCode.toString();
|
||||
}
|
||||
|
||||
/// 视图层级变化
|
||||
/// since v1.0.4
|
||||
void prepare(AMapContext aMapContext) {}
|
||||
|
||||
/// 视图变化
|
||||
/// since v1.0.4
|
||||
void update(AMapContext aMapContext) {}
|
||||
|
||||
void onDispose() {}
|
||||
|
||||
@Deprecated('使用 bindMapController ,计划在1.0.6移除')
|
||||
bindMethodChannel(MethodChannel channel) {}
|
||||
|
||||
/// 注入[AMapController] 方便地图交互
|
||||
bindMapController(AMapController controller) {}
|
||||
|
||||
Widget build(AMapContext aMapContext, Widget child) {
|
||||
/// 默认传递[AMapWidget],有部分场景需要在[AMapWidget]外包装容器,根据传递拓展列表顺序
|
||||
/// 链式执行
|
||||
return child;
|
||||
}
|
||||
|
||||
/// since v1.0.4
|
||||
onCameraMove(CameraPosition cameraPosition) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onCameraMoveEnd(CameraPosition cameraPosition) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onLongPress(LatLng latLng) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onPoiTouched(AMapPoi poi) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onMarkerTap(String value) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onMarkerDragEnd(String value) {}
|
||||
|
||||
/// since v1.0.4
|
||||
onPolylineTap(String value) {}
|
||||
}
|
||||
|
||||
Map<String, AMapExtension> keyByExtensionId(
|
||||
|
@ -1,6 +1,18 @@
|
||||
// Copyright 2023-2024 kuloud
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
/// 上下文
|
||||
class AMapContext {
|
||||
final BuildContext buildContext;
|
||||
final CurrentStep currentStep;
|
||||
@ -14,5 +26,6 @@ class AMapContext {
|
||||
|
||||
enum CurrentStep {
|
||||
preparing,
|
||||
updating,
|
||||
building,
|
||||
}
|
||||
|
@ -23,3 +23,5 @@ export 'bitmap.dart';
|
||||
export 'extension_context.dart';
|
||||
export 'amap_extension.dart';
|
||||
export 'screen_coordinate.dart';
|
||||
|
||||
export '../extension/extensions.dart';
|
||||
|
Reference in New Issue
Block a user