release 1.0.4
This commit is contained in:
parent
b78d128a5e
commit
4b1a1326e8
|
@ -1,3 +1,7 @@
|
|||
## 1.0.4
|
||||
2024-01-04.
|
||||
* 添加 InfoWindowExtension,支持自定义 InfoWindow 样式
|
||||
|
||||
## 1.0.3+1
|
||||
2024-01-03.
|
||||
* 处理lint,更新文档
|
||||
|
|
|
@ -36,7 +36,7 @@ class DemoWidget extends State<AMapDemo> {
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AMapInitializer.init(context, ConstConfig.amapApiKeys);
|
||||
AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys);
|
||||
|
||||
return Scaffold(
|
||||
// ...
|
||||
|
|
|
@ -4,9 +4,6 @@ PODS:
|
|||
- amap_map (1.0.3):
|
||||
- AMap3DMap
|
||||
- Flutter
|
||||
- amap_map_extensions (0.0.1):
|
||||
- AMap3DMap
|
||||
- Flutter
|
||||
- AMapFoundation (1.8.2)
|
||||
- Flutter (1.0.0)
|
||||
- permission_handler_apple (9.1.1):
|
||||
|
@ -14,7 +11,6 @@ PODS:
|
|||
|
||||
DEPENDENCIES:
|
||||
- amap_map (from `.symlinks/plugins/amap_map/ios`)
|
||||
- amap_map_extensions (from `.symlinks/plugins/amap_map_extensions/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
|
||||
|
||||
|
@ -26,8 +22,6 @@ SPEC REPOS:
|
|||
EXTERNAL SOURCES:
|
||||
amap_map:
|
||||
:path: ".symlinks/plugins/amap_map/ios"
|
||||
amap_map_extensions:
|
||||
:path: ".symlinks/plugins/amap_map_extensions/ios"
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
permission_handler_apple:
|
||||
|
@ -36,7 +30,6 @@ EXTERNAL SOURCES:
|
|||
SPEC CHECKSUMS:
|
||||
AMap3DMap: dce25dd3e51e6b92109caa7d0c97fc6055830fb3
|
||||
amap_map: 8773e5cacc760edf208b1e6e61000241d26385fa
|
||||
amap_map_extensions: 6d2affabf1ef14c7af8aa9eeb815b8b8453d92b0
|
||||
AMapFoundation: 9885c48fc3a78fdfb84a0299a2293e56ea3c9fec
|
||||
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
|
||||
permission_handler_apple: e76247795d700c14ea09e3a2d8855d41ee80a2e6
|
||||
|
|
|
@ -6,6 +6,7 @@ import 'package:amap_map_example/pages/map/limit_map_bounds.dart';
|
|||
import 'package:amap_map_example/pages/map/map_my_location.dart';
|
||||
import 'package:amap_map_example/pages/map/map_with_extension_page.dart';
|
||||
import 'package:amap_map_example/pages/map/show_map_page.dart';
|
||||
import 'package:amap_map_example/pages/overlays/custom_info_window.dart';
|
||||
import 'package:amap_map_example/pages/overlays/marker_config.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
|
@ -71,6 +72,14 @@ List<Demo> overlayDemos() {
|
|||
slug: 'marker-config',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => MarkerConfigDemoPage())
|
||||
]),
|
||||
Demo(
|
||||
title: '自定义InfoWindow',
|
||||
category: DemoCategory.overlay,
|
||||
subtitle: '自定义与Marker绑定的InfoWindow样式',
|
||||
slug: 'custom-info-window',
|
||||
configurations: [
|
||||
DemoConfiguration(buildRoute: (context) => CustomInfoWindowDemoPage())
|
||||
])
|
||||
];
|
||||
}
|
||||
|
|
|
@ -8,36 +8,6 @@ import 'package:amap_map_example/theme.dart';
|
|||
import 'package:flutter/material.dart';
|
||||
import 'package:permission_handler/permission_handler.dart';
|
||||
|
||||
// final List<BasePage> _mapDemoPages = <BasePage>[
|
||||
// AllMapConfigDemoPage('总体演示', '演示AMapWidget的所有配置项'),
|
||||
|
||||
// MinMaxZoomDemoPage('指定显示级别范围', '演示指定最小最大级别功能'),
|
||||
// ChangeMapTypePage('切换地图图层', '演示内置的地图图层'),
|
||||
// CustomMapStylePage('自定义地图', '根据自定义的地图样式文件显示地图'),
|
||||
// MultiMapDemoPage('地图多实例', '同时显示多个地图'),
|
||||
// ];
|
||||
|
||||
// final List<BasePage> _interactiveDemoPages = <BasePage>[
|
||||
// MapUIDemoPage('UI控制', 'ui开关演示'),
|
||||
// GesturesDemoPage('手势交互', '手势交互'),
|
||||
// PoiClickDemoPage('点击poi功能', '演示点击poi之后的回调和信息透出'),
|
||||
// MoveCameraDemoPage('改变地图视角', '演示改变地图的中心点、可视区域、缩放级别等功能'),
|
||||
// SnapshotPage('地图截屏', '地图截屏示例'),
|
||||
// ];
|
||||
|
||||
// final List<BasePage> _markerPages = <BasePage>[
|
||||
// MarkerAddWithMapPage("随地图添加", "演示初始化地图时直接添加marker"),
|
||||
// MarkerAddAfterMapPage("单独添加", "演示地图初始化之后单独添加marker功能"),
|
||||
// MarkerCustomIconPage('自定义图标', '演示marker使用自定义图标功能'),
|
||||
// ];
|
||||
|
||||
// final List<BasePage> _overlayPages = <BasePage>[
|
||||
// PolylineDemoPage('Polyline操作', '演示Polyline的相关属性的操作'),
|
||||
// PolylineGeodesicDemoPage('Polyline大地曲线', '演示大地曲线的添加'),
|
||||
// PolylineTextureDemoPage('Polyline纹理线', '演示纹理线的添加'),
|
||||
// PolygonDemoPage('Polygon操作', '演示Polygon的相关属性的操作'),
|
||||
// ];
|
||||
|
||||
final List<Permission> needPermissionList = [
|
||||
Permission.location,
|
||||
Permission.storage,
|
||||
|
@ -82,7 +52,7 @@ class _AMapDemoState extends State<AMapDemo>
|
|||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
AMapInitializer.init(context, ConstConfig.amapApiKeys);
|
||||
AMapInitializer.init(context, apiKey: ConstConfig.amapApiKeys);
|
||||
AMapInitializer.updatePrivacyAgree(ConstConfig.amapPrivacyStatement);
|
||||
return Scaffold(
|
||||
appBar: AppBar(title: const Text('高德地图示例')),
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
// 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_extensions/amap_map_extensions.dart';
|
||||
// import 'package:amap_map_extensions/amap_map_extensions.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'dart:typed_data';
|
||||
|
@ -24,7 +24,7 @@ class MapWithExtensionPage extends StatefulWidget {
|
|||
|
||||
class _MapWithExtensionPageState extends State<MapWithExtensionPage> {
|
||||
List<Widget> _approvalNumberWidget = <Widget>[];
|
||||
final _extension = AmapMapExtensions();
|
||||
// final _extension = AmapMapExtensions();
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
|
|
|
@ -0,0 +1,294 @@
|
|||
import 'dart:async';
|
||||
|
||||
import 'package:amap_map_example/widgets/amap_switch_button.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:amap_map/amap_map.dart';
|
||||
import 'package:x_amap_base/x_amap_base.dart';
|
||||
import 'dart:math';
|
||||
|
||||
/// 自定义[InfoWindow]用例
|
||||
class CustomInfoWindowDemoPage extends StatefulWidget {
|
||||
const CustomInfoWindowDemoPage();
|
||||
|
||||
@override
|
||||
State<StatefulWidget> createState() => _State();
|
||||
}
|
||||
|
||||
class _State extends State<CustomInfoWindowDemoPage> {
|
||||
static final LatLng mapCenter = const LatLng(39.909187, 116.397451);
|
||||
|
||||
Map<String, Marker> _markers = <String, Marker>{};
|
||||
BitmapDescriptor? _markerIcon;
|
||||
String? selectedMarkerId;
|
||||
bool showInfoWindow = false;
|
||||
|
||||
final _infoWindowExtension = InfoWindowExtension(
|
||||
infoWindow: Container(
|
||||
color: Colors.lightBlue.shade400,
|
||||
child: Text('info'),
|
||||
),
|
||||
option: InfoWindowOption(latLng: mapCenter));
|
||||
|
||||
Future<void> _onMapCreated(AMapController controller) async {}
|
||||
|
||||
void _add() {
|
||||
final int markerCount = _markers.length;
|
||||
LatLng markPostion = LatLng(
|
||||
mapCenter.latitude + sin(markerCount * pi / 12.0) / 20.0,
|
||||
mapCenter.longitude + cos(markerCount * pi / 12.0) / 20.0);
|
||||
final Marker marker = Marker(
|
||||
position: markPostion,
|
||||
icon: _markerIcon!,
|
||||
infoWindow: InfoWindow(title: '第 $markerCount 个Marker'),
|
||||
onTap: (markerId) => _onMarkerTapped(markerId),
|
||||
onDragEnd: (markerId, endPosition) =>
|
||||
_onMarkerDragEnd(markerId, endPosition),
|
||||
);
|
||||
|
||||
setState(() {
|
||||
_markers[marker.id] = marker;
|
||||
});
|
||||
}
|
||||
|
||||
void _onMarkerTapped(String markerId) {
|
||||
final Marker? tappedMarker = _markers[markerId];
|
||||
final String? title = tappedMarker!.infoWindow.title;
|
||||
print('$title 被点击了,markerId: $markerId');
|
||||
setState(() {
|
||||
selectedMarkerId = markerId;
|
||||
});
|
||||
}
|
||||
|
||||
void _onMarkerDragEnd(String markerId, LatLng position) {
|
||||
final Marker? tappedMarker = _markers[markerId];
|
||||
final String? title = tappedMarker!.infoWindow.title;
|
||||
print('$title markerId: $markerId 被拖拽到了: $position');
|
||||
}
|
||||
|
||||
void _remove() {
|
||||
final Marker? selectedMarker = _markers[selectedMarkerId];
|
||||
//有选中的Marker
|
||||
if (selectedMarker != null) {
|
||||
setState(() {
|
||||
_markers.remove(selectedMarkerId);
|
||||
});
|
||||
} else {
|
||||
print('无选中的Marker,无法删除');
|
||||
}
|
||||
}
|
||||
|
||||
void _removeAll() {
|
||||
if (_markers.length > 0) {
|
||||
setState(() {
|
||||
_markers.clear();
|
||||
selectedMarkerId = null.toString();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _changeInfo() async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final String newTitle = marker.infoWindow.title! + '*';
|
||||
if (selectedMarkerId != null) {
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
infoWindowParam: marker.infoWindow.copyWith(
|
||||
titleParam: newTitle,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void _changeAnchor() {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final Offset currentAnchor = marker.anchor;
|
||||
double dx = 0;
|
||||
double dy = 0;
|
||||
if (currentAnchor.dx < 1) {
|
||||
dx = currentAnchor.dx + 0.1;
|
||||
} else {
|
||||
dx = 0;
|
||||
}
|
||||
if (currentAnchor.dy < 1) {
|
||||
dy = currentAnchor.dy + 0.1;
|
||||
} else {
|
||||
dy = 0;
|
||||
}
|
||||
final Offset newAnchor = Offset(dx, dy);
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
anchorParam: newAnchor,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void _changePosition() {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final LatLng current = marker.position;
|
||||
final Offset offset = Offset(
|
||||
mapCenter.latitude - current.latitude,
|
||||
mapCenter.longitude - current.longitude,
|
||||
);
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
positionParam: LatLng(
|
||||
mapCenter.latitude + offset.dy,
|
||||
mapCenter.longitude + offset.dx,
|
||||
),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _changeAlpha() async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final double current = marker.alpha;
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
alphaParam: current < 0.1 ? 1.0 : current * 0.75,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _changeRotation() async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
final double current = marker.rotation;
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
rotationParam: current == 330.0 ? 0.0 : current + 30.0,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _toggleVisible(value) async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
|
||||
setState(() {
|
||||
showInfoWindow = value;
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
// visibleParam: value,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
Future<void> _toggleDraggable(value) async {
|
||||
final Marker marker = _markers[selectedMarkerId]!;
|
||||
setState(() {
|
||||
_markers[selectedMarkerId!] = marker.copyWith(
|
||||
draggableParam: value,
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
///以下几种获取自定图片的方式使用其中一种即可。
|
||||
//最简单的方式
|
||||
if (null == _markerIcon) {
|
||||
_markerIcon = BitmapDescriptor.fromIconPath('assets/location_marker.png');
|
||||
}
|
||||
|
||||
_infoWindowExtension.option?.show =
|
||||
_markers[selectedMarkerId] != null && showInfoWindow;
|
||||
_infoWindowExtension.option?.latLng = _markers[selectedMarkerId]?.position;
|
||||
|
||||
final AMapWidget map = AMapWidget(
|
||||
onMapCreated: _onMapCreated,
|
||||
markers: Set<Marker>.of(_markers.values),
|
||||
extensions: [_infoWindowExtension],
|
||||
);
|
||||
return Container(
|
||||
height: MediaQuery.of(context).size.height,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.start,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Container(
|
||||
height: MediaQuery.of(context).size.height * 0.6,
|
||||
width: MediaQuery.of(context).size.width,
|
||||
child: map,
|
||||
),
|
||||
Expanded(
|
||||
child: SingleChildScrollView(
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
|
||||
children: <Widget>[
|
||||
Row(
|
||||
children: <Widget>[
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('添加'),
|
||||
onPressed: _add,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('移除'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _remove,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('更新InfoWidow'),
|
||||
onPressed:
|
||||
(selectedMarkerId == null) ? null : _changeInfo,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改锚点'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAnchor,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改透明度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeAlpha,
|
||||
),
|
||||
],
|
||||
),
|
||||
Column(
|
||||
children: <Widget>[
|
||||
TextButton(
|
||||
child: const Text('全部移除'),
|
||||
onPressed: _markers.length > 0 ? _removeAll : null,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('允许拖动'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleDraggable,
|
||||
defaultValue: false,
|
||||
),
|
||||
AMapSwitchButton(
|
||||
label: Text('显示'),
|
||||
onSwitchChanged: (selectedMarkerId == null)
|
||||
? null
|
||||
: _toggleVisible,
|
||||
defaultValue: true,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改坐标'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changePosition,
|
||||
),
|
||||
TextButton(
|
||||
child: const Text('修改旋转角度'),
|
||||
onPressed: (selectedMarkerId == null)
|
||||
? null
|
||||
: _changeRotation,
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
)
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
|
@ -23,7 +23,8 @@ dependencies:
|
|||
# the parent directory to use the current plugin's version.
|
||||
path: ../
|
||||
|
||||
amap_map_extensions: ^0.0.1
|
||||
# amap_map_extensions: ^0.0.1
|
||||
# amap_map_extensions:
|
||||
# path: ../../amap_map_extensions
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
//高德地图参数设置
|
||||
|
|
|
@ -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}';
|
||||
}
|
||||
}
|
|
@ -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';
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
name: amap_map
|
||||
description: Amap SDK Flutter plugin for integrating AMapSDK in iOS and Android applications.
|
||||
version: 1.0.3+1
|
||||
version: 1.0.4
|
||||
homepage: https://github.com/kuloud/amap_map
|
||||
issue_tracker: https://github.com/kuloud/amap_map/issues
|
||||
platforms:
|
||||
|
@ -18,10 +18,11 @@ dependencies:
|
|||
flutter:
|
||||
sdk: flutter
|
||||
flutter_plugin_android_lifecycle: ^2.0.17
|
||||
plugin_platform_interface: ^2.0.0
|
||||
plugin_platform_interface: ^2.1.8
|
||||
stream_transform: ^2.0.0
|
||||
|
||||
x_amap_base: ^1.0.0+2
|
||||
x_amap_base: ^1.0.1
|
||||
# provider: ^6.1.1
|
||||
# x_amap_base:
|
||||
# path: ../x_amap_base
|
||||
dev_dependencies:
|
||||
|
|
Loading…
Reference in New Issue