提交 fc4db448 authored 作者: houziyu's avatar houziyu

Initial commit

上级
.DS_Store
.dart_tool/
.packages
.pub/
build/
.idea/
*.iml
**/pubspec.lock
.settings/
.project
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 84f3d28555368a70270e9ac8390a9441df95e752
channel: stable
project_type: plugin
## 【3.0.0】 - 2021-11-23.
* AMapWidget初始化时需要传入高德隐私合规配置参数privacyStatement
* 高德SDK合规使用方案请参考:https://lbs.amap.com/news/sdkhgsy
* 适配高德地图SDK 8.1.0及以后版本
## [2.0.2] - 2021-08-19.
* 修复在初始化地图时添加的Marker无法点击、移除的问题
* 修复在初始化地图时添加的Polyline无法点击、移除、修改的问题
* 修复在初始化地图时添加的Polygon无法点击、移除、修改的问题
## [2.0.1] - 2021-04-21.
* 支持Flutter 2.0.0以上版本
* 升级支持null-safety
* 修复2.0版本自定义地图样式不生效的问题
## [2.0.0] - 2021-04-21.
* 支持Flutter 2.0.0以上版本
* 升级支持null-safety
## [1.0.2] - 2021-02-02.
* debug模式,Android native端输出调试日志,方便排查问题。
## [1.0.1] - 2021-01-27.
* 修复iOS端动态库依赖静态库导致的pod install失败问题。
## [1.0.0] - 2020-12-22.
* 1.0.0版本发布
\ No newline at end of file
Copyright <2020> <lbs.amap.com>
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# amap_flutter_map
基于[高德开放平台地图SDK](https://lbs.amap.com/api/)的flutter插件
## Usage
使用Flutter插件,请参考[在Flutter里使用Packages](https://flutter.cn/docs/development/packages-and-plugins/using-packages), 添加amap_flutter_map的引用
## 准备工作
* 登录[高德开放平台官网](https://lbs.amap.com/)申请ApiKey。Android平台申请配置key请参考[Android获取key](https://lbs.amap.com/api/poi-sdk-android/develop/create-project/get-key/?sug_index=2), iOS平台申请配置请参考[iOS获取key](https://lbs.amap.com/api/poi-sdk-ios/develop/create-project/get-key/?sug_index=1)
* 引入高德地图SDK,Android平台请参考[Android Sudio配置工程](https://lbs.amap.com/api/android-sdk/guide/create-project/android-studio-create-project), iOS平台请参考[ios安装地图SDK](https://lbs.amap.com/api/ios-sdk/guide/create-project/cocoapods)
* iOS端插件使用特殊配置:Flutter 1.22.0 之前(之后的版本可以不添加该配置),iOS端的UiKitView还只是preview状态, 默认是不支持的, 需要手动打开开关, 需要在iOS工程的info.plist添加如下配置:
``` XML
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
```
## 使用示例
``` Dart
import 'package:amap_flutter_map_example/base_page.dart';
import 'package:flutter/material.dart';
import 'package:amap_flutter_map/amap_flutter_map.dart';
import 'package:amap_flutter_base/amap_flutter_base.dart';
class ShowMapPage extends BasePage {
ShowMapPage(String title, String subTitle) : super(title, subTitle);
@override
Widget build(BuildContext context) {
return _ShowMapPageBody();
}
}
class _ShowMapPageBody extends StatefulWidget {
@override
State<StatefulWidget> createState() => _ShowMapPageState();
}
class _ShowMapPageState extends State<_ShowMapPageBody> {
static final CameraPosition _kInitialPosition = const CameraPosition(
target: LatLng(39.909187, 116.397451),
zoom: 10.0,
);
List<Widget> _approvalNumberWidget = List<Widget>();
@override
Widget build(BuildContext context) {
final AMapWidget map = AMapWidget(
initialCameraPosition: _kInitialPosition,
onMapCreated: onMapCreated,
);
return ConstrainedBox(
constraints: BoxConstraints.expand(),
child: Stack(
alignment: Alignment.center,
children: [
Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: map,
),
Positioned(
right: 10,
bottom: 15,
child: Container(
alignment: Alignment.centerLeft,
child: Column(
mainAxisAlignment: MainAxisAlignment.start,
children: _approvalNumberWidget),
))
],
),
);
}
AMapController _mapController;
void onMapCreated(AMapController controller) {
setState(() {
_mapController = controller;
getApprovalNumber();
});
}
/// 获取审图号
void getApprovalNumber() async {
//普通地图审图号
String mapContentApprovalNumber =
await _mapController?.getMapContentApprovalNumber();
//卫星地图审图号
String satelliteImageApprovalNumber =
await _mapController?.getSatelliteImageApprovalNumber();
setState(() {
if (null != mapContentApprovalNumber) {
_approvalNumberWidget.add(Text(mapContentApprovalNumber));
}
if (null != satelliteImageApprovalNumber) {
_approvalNumberWidget.add(Text(satelliteImageApprovalNumber));
}
});
print('地图审图号(普通地图): $mapContentApprovalNumber');
print('地图审图号(卫星地图): $satelliteImageApprovalNumber');
}
}
```
## 已知问题:
1. Flutter插件在iOS端,MapView销毁时,一定概率触发Main Thread Checker的报警,
经过对比测试确认是Flutter的bug所致;https://github.com/flutter/flutter/issues/68490
(对比1.25.0-8.1.pre版本已修复,从github的issues中得知,有其它开发着反馈1.24.0-6.0.pre已修复;该问题依赖Flutter升级修复)
*.iml
.gradle
/local.properties
/.idea/workspace.xml
/.idea/libraries
.DS_Store
/build
/captures
group 'com.amap.flutter.amap_flutter_map'
version '1.0'
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
rootProject.allprojects {
repositories {
google()
jcenter()
}
}
apply plugin: 'com.android.library'
android {
compileSdkVersion 31
defaultConfig {
minSdkVersion 16
}
lintOptions {
disable 'InvalidPackage'
}
}
dependencies {
compileOnly 'com.amap.api:3dmap:8.1.0'
implementation 'com.amap.api:search:8.1.0'
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
rootProject.name = 'amap_flutter_map'
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amap.flutter.amap_flutter_map">
</manifest>
package com.amap.flutter.map;
import android.app.Activity;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import com.amap.flutter.map.utils.LogUtil;
import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.embedding.engine.plugins.activity.ActivityAware;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.embedding.engine.plugins.lifecycle.FlutterLifecycleAdapter;
import io.flutter.plugin.common.PluginRegistry;
/**
* AmapFlutterMapPlugin
*/
public class AMapFlutterMapPlugin implements
FlutterPlugin,
ActivityAware {
private static final String CLASS_NAME = "AMapFlutterMapPlugin";
private FlutterPluginBinding pluginBinding;
private Lifecycle lifecycle;
private static final String VIEW_TYPE = "com.amap.flutter.map";
public static void registerWith(PluginRegistry.Registrar registrar) {
LogUtil.i(CLASS_NAME, "registerWith=====>");
final Activity activity = registrar.activity();
if (activity == null) {
LogUtil.w(CLASS_NAME, "activity is null!!!");
return;
}
if (activity instanceof LifecycleOwner) {
registrar
.platformViewRegistry()
.registerViewFactory(
VIEW_TYPE,
new AMapPlatformViewFactory(
registrar.messenger(),
new LifecycleProvider() {
@Override
public Lifecycle getLifecycle() {
return ((LifecycleOwner) activity).getLifecycle();
}
}));
} else {
registrar
.platformViewRegistry()
.registerViewFactory(
VIEW_TYPE,
new AMapPlatformViewFactory(registrar.messenger(), new ProxyLifecycleProvider(activity)));
}
}
public AMapFlutterMapPlugin() {
}
// FlutterPlugin
@Override
public void onAttachedToEngine(@NonNull FlutterPluginBinding binding) {
LogUtil.i(CLASS_NAME, "onAttachedToEngine==>");
pluginBinding = binding;
binding
.getPlatformViewRegistry()
.registerViewFactory(
VIEW_TYPE,
new AMapPlatformViewFactory(
binding.getBinaryMessenger(),
new LifecycleProvider() {
@Nullable
@Override
public Lifecycle getLifecycle() {
return lifecycle;
}
}));
}
@Override
public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
LogUtil.i(CLASS_NAME, "onDetachedFromEngine==>");
pluginBinding = null;
}
// ActivityAware
@Override
public void onAttachedToActivity(@NonNull ActivityPluginBinding binding) {
LogUtil.i(CLASS_NAME, "onAttachedToActivity==>");
lifecycle = FlutterLifecycleAdapter.getActivityLifecycle(binding);
}
@Override
public void onDetachedFromActivity() {
LogUtil.i(CLASS_NAME, "onDetachedFromActivity==>");
lifecycle = null;
}
@Override
public void onReattachedToActivityForConfigChanges(@NonNull ActivityPluginBinding binding) {
LogUtil.i(CLASS_NAME, "onReattachedToActivityForConfigChanges==>");
onAttachedToActivity(binding);
}
@Override
public void onDetachedFromActivityForConfigChanges() {
LogUtil.i(CLASS_NAME, "onDetachedFromActivityForConfigChanges==>");
this.onDetachedFromActivity();
}
}
package com.amap.flutter.map;
import android.content.Context;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.flutter.map.core.AMapOptionsSink;
import com.amap.flutter.map.utils.LogUtil;
import java.util.List;
import io.flutter.plugin.common.BinaryMessenger;
/**
* @author whm
* @date 2020/10/29 10:13 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class AMapOptionsBuilder implements AMapOptionsSink {
private static final String CLASS_NAME = "AMapOptionsBuilder";
private final AMapOptions options = new AMapOptions();
private CustomMapStyleOptions customMapStyleOptions;
private MyLocationStyle myLocationStyle;
private float minZoomLevel = 3;
private float maxZoomLevel = 20;
private LatLngBounds latLngBounds;
private boolean trafficEnabled = true;
private boolean touchPoiEnabled = true;
private boolean buildingsEnabled = true;
private boolean labelsEnabled = true;
private float anchorX = 2.0F;
private float anchorY = 2.0F;
private Object initialMarkers;
private Object initialPolylines;
private Object initialPolygons;
AMapPlatformView build(int id,
Context context,
BinaryMessenger binaryMessenger,
LifecycleProvider lifecycleProvider) {
try {
//iOS端没有放大缩小UI, Android端强制隐藏
options.zoomControlsEnabled(false);
final AMapPlatformView aMapPlatformView = new AMapPlatformView(id, context, binaryMessenger, lifecycleProvider, options);
if (null != customMapStyleOptions) {
aMapPlatformView.getMapController().setCustomMapStyleOptions(customMapStyleOptions);
}
if (null != myLocationStyle) {
aMapPlatformView.getMapController().setMyLocationStyle(myLocationStyle);
}
if (anchorX >= 0
&& anchorX <= 1.0
&& anchorY <= 1.0
&& anchorY >= 0) {
aMapPlatformView.getMapController().setScreenAnchor( anchorX, anchorY);
}
aMapPlatformView.getMapController().setMinZoomLevel(minZoomLevel);
aMapPlatformView.getMapController().setMaxZoomLevel(maxZoomLevel);
if (null != latLngBounds) {
aMapPlatformView.getMapController().setLatLngBounds(latLngBounds);
}
aMapPlatformView.getMapController().setTrafficEnabled(trafficEnabled);
aMapPlatformView.getMapController().setTouchPoiEnabled(touchPoiEnabled);
aMapPlatformView.getMapController().setBuildingsEnabled(buildingsEnabled);
aMapPlatformView.getMapController().setLabelsEnabled(labelsEnabled);
if (null != initialMarkers) {
List<Object> markerList = (List<Object>) initialMarkers;
aMapPlatformView.getMarkersController().addByList(markerList);
}
if (null != initialPolylines) {
List<Object> markerList = (List<Object>) initialPolylines;
aMapPlatformView.getPolylinesController().addByList(markerList);
}
if (null != initialPolygons) {
List<Object> polygonList = (List<Object>) initialPolygons;
aMapPlatformView.getPolygonsController().addByList(polygonList);
}
return aMapPlatformView;
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "build", e);
}
return null;
}
@Override
public void setCamera(CameraPosition camera) {
options.camera(camera);
}
@Override
public void setMapType(int mapType) {
options.mapType(mapType);
}
@Override
public void setCustomMapStyleOptions(CustomMapStyleOptions customMapStyleOptions) {
this.customMapStyleOptions = customMapStyleOptions;
}
@Override
public void setMyLocationStyle(MyLocationStyle myLocationStyle) {
this.myLocationStyle = myLocationStyle;
}
@Override
public void setScreenAnchor(float x, float y) {
anchorX = x;
anchorY = y;
}
@Override
public void setMinZoomLevel(float minZoomLevel) {
this.minZoomLevel = minZoomLevel;
}
@Override
public void setMaxZoomLevel(float maxZoomLevel) {
this.maxZoomLevel = maxZoomLevel;
}
@Override
public void setLatLngBounds(LatLngBounds latLngBounds) {
this.latLngBounds = latLngBounds;
}
@Override
public void setTrafficEnabled(boolean trafficEnabled) {
this.trafficEnabled = trafficEnabled;
}
@Override
public void setTouchPoiEnabled(boolean touchPoiEnabled) {
this.touchPoiEnabled = touchPoiEnabled;
}
@Override
public void setBuildingsEnabled(boolean buildingsEnabled) {
this.buildingsEnabled = buildingsEnabled;
}
@Override
public void setLabelsEnabled(boolean labelsEnabled) {
this.labelsEnabled = labelsEnabled;
}
@Override
public void setCompassEnabled(boolean compassEnabled) {
options.compassEnabled(compassEnabled);
}
@Override
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
options.zoomGesturesEnabled(zoomGesturesEnabled);
}
@Override
public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
options.scrollGesturesEnabled(scrollGesturesEnabled);
}
@Override
public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
options.rotateGesturesEnabled(rotateGesturesEnabled);
}
@Override
public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
options.tiltGesturesEnabled(tiltGesturesEnabled);
}
@Override
public void setScaleEnabled(boolean scaleEnabled) {
options.scaleControlsEnabled(scaleEnabled);
}
@Override
public void setInitialMarkers(Object markersObject) {
this.initialMarkers = markersObject;
}
@Override
public void setInitialPolylines(Object polylinesObject) {
this.initialPolylines = polylinesObject;
}
@Override
public void setInitialPolygons(Object polygonsObject) {
this.initialPolygons = polygonsObject;
}
}
package com.amap.flutter.map;
import android.content.Context;
import android.os.Bundle;
import android.view.View;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.lifecycle.DefaultLifecycleObserver;
import androidx.lifecycle.LifecycleOwner;
import com.amap.api.maps.AMap;
import com.amap.api.maps.AMapOptions;
import com.amap.api.maps.TextureMapView;
import com.amap.flutter.map.core.MapController;
import com.amap.flutter.map.overlays.marker.MarkersController;
import com.amap.flutter.map.overlays.polygon.PolygonsController;
import com.amap.flutter.map.overlays.polyline.PolylinesController;
import com.amap.flutter.map.utils.LogUtil;
import java.util.HashMap;
import java.util.Map;
import io.flutter.embedding.engine.plugins.activity.ActivityPluginBinding;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.platform.PlatformView;
/**
* @author whm
* @date 2020/10/27 5:49 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class AMapPlatformView
implements
DefaultLifecycleObserver,
ActivityPluginBinding.OnSaveInstanceStateListener,
MethodChannel.MethodCallHandler,
PlatformView {
private static final String CLASS_NAME = "AMapPlatformView";
private final MethodChannel methodChannel;
private MapController mapController;
private MarkersController markersController;
private PolylinesController polylinesController;
private PolygonsController polygonsController;
private TextureMapView mapView;
private boolean disposed = false;
private final Map<String, MyMethodCallHandler> myMethodCallHandlerMap;
AMapPlatformView(int id,
Context context,
BinaryMessenger binaryMessenger,
LifecycleProvider lifecycleProvider,
AMapOptions options) {
methodChannel = new MethodChannel(binaryMessenger, "amap_flutter_map_" + id);
methodChannel.setMethodCallHandler(this);
myMethodCallHandlerMap = new HashMap<String, MyMethodCallHandler>(8);
try {
mapView = new TextureMapView(context, options);
AMap amap = mapView.getMap();
mapController = new MapController(methodChannel, mapView);
markersController = new MarkersController(methodChannel, amap);
polylinesController = new PolylinesController(methodChannel, amap);
polygonsController = new PolygonsController(methodChannel, amap);
initMyMethodCallHandlerMap();
lifecycleProvider.getLifecycle().addObserver(this);
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "<init>", e);
}
}
private void initMyMethodCallHandlerMap() {
String[] methodIdArray = mapController.getRegisterMethodIdArray();
if (null != methodIdArray && methodIdArray.length > 0) {
for (String methodId : methodIdArray) {
myMethodCallHandlerMap.put(methodId, mapController);
}
}
methodIdArray = markersController.getRegisterMethodIdArray();
if (null != methodIdArray && methodIdArray.length > 0) {
for (String methodId : methodIdArray) {
myMethodCallHandlerMap.put(methodId, markersController);
}
}
methodIdArray = polylinesController.getRegisterMethodIdArray();
if (null != methodIdArray && methodIdArray.length > 0) {
for (String methodId : methodIdArray) {
myMethodCallHandlerMap.put(methodId, polylinesController);
}
}
methodIdArray = polygonsController.getRegisterMethodIdArray();
if (null != methodIdArray && methodIdArray.length > 0) {
for (String methodId : methodIdArray) {
myMethodCallHandlerMap.put(methodId, polygonsController);
}
}
}
public MapController getMapController() {
return mapController;
}
public MarkersController getMarkersController() {
return markersController;
}
public PolylinesController getPolylinesController() {
return polylinesController;
}
public PolygonsController getPolygonsController() {
return polygonsController;
}
@Override
public void onMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
LogUtil.i(CLASS_NAME, "onMethodCall==>" + call.method + ", arguments==> " + call.arguments);
String methodId = call.method;
if (myMethodCallHandlerMap.containsKey(methodId)) {
myMethodCallHandlerMap.get(methodId).doMethodCall(call, result);
} else {
LogUtil.w(CLASS_NAME, "onMethodCall, the methodId: " + call.method + ", not implemented");
result.notImplemented();
}
}
@Override
public void onCreate(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onCreate==>");
try {
if (disposed) {
return;
}
if (null != mapView) {
mapView.onCreate(null);
}
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onCreate", e);
}
}
@Override
public void onStart(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onStart==>");
}
@Override
public void onResume(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onResume==>");
try {
if (disposed) {
return;
}
if (null != mapView) {
mapView.onResume();
}
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onResume", e);
}
}
@Override
public void onPause(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onPause==>");
try {
if (disposed) {
return;
}
mapView.onPause();
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onPause", e);
}
}
@Override
public void onStop(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onStop==>");
}
@Override
public void onDestroy(@NonNull LifecycleOwner owner) {
LogUtil.i(CLASS_NAME, "onDestroy==>");
try {
if (disposed) {
return;
}
destroyMapViewIfNecessary();
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onDestroy", e);
}
}
@Override
public void onSaveInstanceState(@NonNull Bundle bundle) {
LogUtil.i(CLASS_NAME, "onDestroy==>");
try {
if (disposed) {
return;
}
mapView.onSaveInstanceState(bundle);
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onSaveInstanceState", e);
}
}
@Override
public void onRestoreInstanceState(@Nullable Bundle bundle) {
LogUtil.i(CLASS_NAME, "onDestroy==>");
try {
if (disposed) {
return;
}
mapView.onCreate(bundle);
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onRestoreInstanceState", e);
}
}
@Override
public View getView() {
LogUtil.i(CLASS_NAME, "getView==>");
return mapView;
}
@Override
public void dispose() {
LogUtil.i(CLASS_NAME, "dispose==>");
try {
if (disposed) {
return;
}
methodChannel.setMethodCallHandler(null);
destroyMapViewIfNecessary();
disposed = true;
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "dispose", e);
}
}
private void destroyMapViewIfNecessary() {
if (mapView == null) {
return;
}
mapView.onDestroy();
}
}
package com.amap.flutter.map;
import android.content.Context;
import com.amap.api.maps.model.CameraPosition;
import com.amap.flutter.map.utils.ConvertUtil;
import com.amap.flutter.map.utils.LogUtil;
import java.util.Map;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.StandardMessageCodec;
import io.flutter.plugin.platform.PlatformView;
import io.flutter.plugin.platform.PlatformViewFactory;
/**
* @author whm
* @date 2020/10/27 4:08 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class AMapPlatformViewFactory extends PlatformViewFactory {
private static final String CLASS_NAME = "AMapPlatformViewFactory";
private final BinaryMessenger binaryMessenger;
private final LifecycleProvider lifecycleProvider;
AMapPlatformViewFactory(BinaryMessenger binaryMessenger,
LifecycleProvider lifecycleProvider) {
super(StandardMessageCodec.INSTANCE);
this.binaryMessenger = binaryMessenger;
this.lifecycleProvider = lifecycleProvider;
}
@Override
public PlatformView create(Context context, int viewId, Object args) {
final AMapOptionsBuilder builder = new AMapOptionsBuilder();
Map<String, Object> params = null;
try {
ConvertUtil.density = context.getResources().getDisplayMetrics().density;
params = (Map<String, Object>) args;
LogUtil.i(CLASS_NAME,"create params==>" + params);
if (params.containsKey("privacyStatement")) {
ConvertUtil.setPrivacyStatement(context, params.get("privacyStatement"));
}
Object options = ((Map<String, Object>) args).get("options");
if(null != options) {
ConvertUtil.interpretAMapOptions(options, builder);
}
if (params.containsKey("initialCameraPosition")) {
CameraPosition cameraPosition = ConvertUtil.toCameraPosition(params.get("initialCameraPosition"));
builder.setCamera(cameraPosition);
}
if (params.containsKey("markersToAdd")) {
builder.setInitialMarkers(params.get("markersToAdd"));
}
if (params.containsKey("polylinesToAdd")) {
builder.setInitialPolylines(params.get("polylinesToAdd"));
}
if (params.containsKey("polygonsToAdd")) {
builder.setInitialPolygons(params.get("polygonsToAdd"));
}
if (params.containsKey("apiKey")) {
ConvertUtil.checkApiKey(params.get("apiKey"));
}
if (params.containsKey("debugMode")) {
LogUtil.isDebugMode = ConvertUtil.toBoolean(params.get("debugMode"));
}
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "create", e);
}
return builder.build(viewId, context, binaryMessenger, lifecycleProvider);
}
}
package com.amap.flutter.map;
import androidx.lifecycle.Lifecycle;
/**
* @author whm
* @date 2020/11/8 6:17 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public interface LifecycleProvider {
Lifecycle getLifecycle();
}
package com.amap.flutter.map;
import androidx.annotation.NonNull;
import java.util.List;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/10 9:47 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public interface MyMethodCallHandler {
public void doMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result);
/**
* 获取注册的{@link io.flutter.plugin.common.MethodCall#method}
* @return
*/
public abstract String[] getRegisterMethodIdArray();
}
package com.amap.flutter.map;
import android.app.Activity;
import android.app.Application;
import android.os.Bundle;
import androidx.annotation.NonNull;
import androidx.lifecycle.Lifecycle;
import androidx.lifecycle.LifecycleOwner;
import androidx.lifecycle.LifecycleRegistry;
import com.amap.flutter.map.utils.LogUtil;
/**
* This class provides a {@link LifecycleOwner} for the activity driven by {@link
* Application.ActivityLifecycleCallbacks}.
*
* <p>This is used in the case where a direct Lifecycle/Owner is not available.
*/
public class ProxyLifecycleProvider
implements
Application.ActivityLifecycleCallbacks,
LifecycleOwner,
LifecycleProvider {
private static final String CLASS_NAME = "ProxyLifecycleProvider";
private final LifecycleRegistry lifecycle = new LifecycleRegistry(this);
private final int registrarActivityHashCode;
public ProxyLifecycleProvider(Activity activity) {
this.registrarActivityHashCode = activity.hashCode();
activity.getApplication().registerActivityLifecycleCallbacks(this);
LogUtil.i(CLASS_NAME, "<init>");
}
@Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_CREATE);
LogUtil.i(CLASS_NAME, "onActivityCreated==>");
}
@Override
public void onActivityStarted(Activity activity) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_START);
LogUtil.i(CLASS_NAME, "onActivityStarted==>");
}
@Override
public void onActivityResumed(Activity activity) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_RESUME);
LogUtil.i(CLASS_NAME, "onActivityResumed==>");
}
@Override
public void onActivityPaused(Activity activity) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_PAUSE);
LogUtil.i(CLASS_NAME, "onActivityPaused==>");
}
@Override
public void onActivityStopped(Activity activity) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_STOP);
LogUtil.i(CLASS_NAME, "onActivityStopped==>");
}
@Override
public void onActivitySaveInstanceState(Activity activity, Bundle outState) {
}
@Override
public void onActivityDestroyed(Activity activity) {
if (activity.hashCode() != registrarActivityHashCode) {
return;
}
activity.getApplication().unregisterActivityLifecycleCallbacks(this);
lifecycle.handleLifecycleEvent(Lifecycle.Event.ON_DESTROY);
LogUtil.i(CLASS_NAME, "onActivityDestroyed==>");
}
@NonNull
@Override
public Lifecycle getLifecycle() {
return lifecycle;
}
}
\ No newline at end of file
package com.amap.flutter.map.core;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.MyTrafficStyle;
/**
* @author whm
* @date 2020/10/29 9:56 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public interface AMapOptionsSink {
public void setCamera(CameraPosition camera);
public void setMapType(int mapType);
public void setCustomMapStyleOptions(CustomMapStyleOptions customMapStyleOptions);
public void setMyLocationStyle(MyLocationStyle myLocationStyle);
public void setScreenAnchor(float x, float y);
public void setMinZoomLevel(float minZoomLevel);
public void setMaxZoomLevel(float maxZoomLevel);
public void setLatLngBounds(LatLngBounds latLngBounds);
public void setTrafficEnabled(boolean trafficEnabled);
public void setTouchPoiEnabled(boolean touchPoiEnabled);
public void setBuildingsEnabled(boolean buildingsEnabled);
public void setLabelsEnabled(boolean labelsEnabled);
public void setCompassEnabled(boolean compassEnabled);
public void setScaleEnabled(boolean scaleEnabled);
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled);
public void setScrollGesturesEnabled(boolean scrollGesturesEnabled);
public void setRotateGesturesEnabled(boolean rotateGesturesEnabled);
public void setTiltGesturesEnabled(boolean tiltGesturesEnabled);
public void setInitialMarkers(Object initialMarkers);
public void setInitialPolylines(Object initialPolylines);
public void setInitialPolygons(Object initialPolygons);
}
package com.amap.flutter.map.core;
import android.util.Log;
import com.amap.api.services.core.AMapException;
import com.amap.api.services.core.PoiItem;
import com.amap.api.services.geocoder.RegeocodeAddress;
import com.amap.api.services.geocoder.RegeocodeResult;
import com.amap.api.services.help.Tip;
import com.amap.api.services.poisearch.PoiResult;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @Author : shixiaochen
* @Time : 2022/4/15
* @Description :
*/
public class Utils {
/**
* poi搜索 数据
*
* @param poiResult poiResult
* @param code 响应码
* @return 返回数据
*/
public static List<Map<String, Object>> buildSearchResultList(PoiResult poiResult, int code) {
List<Map<String, Object>> result = new ArrayList<>();
if (code == AMapException.CODE_AMAP_SUCCESS) {
ArrayList<PoiItem> list = poiResult.getPois();
Log.d("TAG", "buildSearchResultList: list = " + list);
if (list != null) {
for (PoiItem poiItem : list) {
HashMap<String, Object> map = new HashMap<>();
map.put("latitude", poiItem.getLatLonPoint().getLatitude());
map.put("longitude", poiItem.getLatLonPoint().getLongitude());
map.put("provinceName", poiItem.getProvinceName());
map.put("provinceCode", poiItem.getProvinceCode());
map.put("cityName", poiItem.getCityName());
map.put("cityCode", poiItem.getCityCode());
map.put("adName", poiItem.getAdName());
map.put("businessArea", poiItem.getBusinessArea());
map.put("snippet", poiItem.getSnippet());
map.put("title", poiItem.getTitle());
result.add(map);
}
}
}
return result;
}
/**
* inputTips 数据
*
* @param list tips
* @param code 响应码
* @return 返回数据
*/
public static List<Map<String, Object>> buildSearchInputResultList(List<Tip> list, int code) {
List<Map<String, Object>> result = new ArrayList<>();
if (code == AMapException.CODE_AMAP_SUCCESS) {
Log.d("TAG", "buildSearchResultList: list = " + list);
if (list != null) {
for (Tip tip : list) {
HashMap<String, Object> map = new HashMap<>();
map.put("name", tip.getName());
map.put("address", tip.getAddress());
map.put("adCode", tip.getAdcode());
map.put("district", tip.getDistrict());
map.put("poiID", tip.getPoiID());
map.put("typeCode", tip.getTypeCode());
if (tip.getPoint() != null) {
map.put("latitude", tip.getPoint().getLatitude());
map.put("longitude", tip.getPoint().getLongitude());
} else {
map.put("latitude", null);
map.put("longitude", null);
}
result.add(map);
}
}
}
return result;
}
/**
* SearchRegeocode
*
* @param regeocode regeocode
* @param code 响应码
* @return 返回数据
*/
public static Map<String, Object> buildSearchRegeocodeResultList(RegeocodeResult regeocode, int code) {
Map<String, Object> result = new HashMap<>();
if (code == AMapException.CODE_AMAP_SUCCESS) {
if (regeocode != null && regeocode.getRegeocodeAddress() != null) {
RegeocodeAddress address = regeocode.getRegeocodeAddress();
result.put("province", address.getProvince());
result.put("city", address.getCity());
result.put("town", address.getTownship());
result.put("street", address.getBuilding());
result.put("district", address.getDistrict());
result.put("address", address.getFormatAddress());
result.put("adCode", address.getAdCode());
result.put("cityCode", address.getCityCode());
result.put("country", address.getCountry());
result.put("neighborhood", address.getNeighborhood());
result.put("townCode", address.getTowncode());
}
}
return result;
}
}
package com.amap.flutter.map.overlays;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.TextureMapView;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/10 7:42 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public abstract class AbstractOverlayController<T> {
protected final Map<String, T> controllerMapByDartId;
protected final Map<String, String> idMapByOverlyId;
protected final MethodChannel methodChannel;
protected final AMap amap;
public AbstractOverlayController(MethodChannel methodChannel, AMap amap){
this.methodChannel = methodChannel;
this.amap = amap;
controllerMapByDartId = new HashMap<String, T>(12);
idMapByOverlyId = new HashMap<String, String>(12);
}
}
package com.amap.flutter.map.overlays.marker;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
/**
* @author whm
* @date 2020/11/6 6:18 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class MarkerController implements MarkerOptionsSink {
private final Marker marker;
private final String markerId;
MarkerController(Marker marker) {
this.marker = marker;
markerId = marker.getId();
}
public String getMarkerId() {
return markerId;
}
public void remove() {
if (null != marker) {
marker.remove();
}
}
public LatLng getPosition() {
if(null != marker) {
return marker.getPosition();
}
return null;
}
@Override
public void setAlpha(float alpha) {
marker.setAlpha(alpha);
}
@Override
public void setAnchor(float u, float v) {
marker.setAnchor(u, v);
}
@Override
public void setDraggable(boolean draggable) {
marker.setDraggable(draggable);
}
@Override
public void setFlat(boolean flat) {
marker.setFlat(flat);
}
@Override
public void setIcon(BitmapDescriptor bitmapDescriptor) {
marker.setIcon(bitmapDescriptor);
}
@Override
public void setTitle(String title) {
marker.setTitle(title);
}
@Override
public void setSnippet(String snippet) {
marker.setSnippet(snippet);
}
@Override
public void setPosition(LatLng position) {
marker.setPosition(position);
}
@Override
public void setRotation(float rotation) {
marker.setRotateAngle(rotation);
}
@Override
public void setVisible(boolean visible) {
marker.setVisible(visible);
}
@Override
public void setZIndex(float zIndex) {
marker.setZIndex(zIndex);
}
@Override
public void setInfoWindowEnable(boolean enable) {
marker.setInfoWindowEnable(enable);
}
@Override
public void setClickable(boolean clickable) {
marker.setClickable(clickable);
}
public void showInfoWindow() {
marker.showInfoWindow();
}
public void hideInfoWindow() {
marker.hideInfoWindow();
}
}
package com.amap.flutter.map.overlays.marker;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.MarkerOptions;
/**
* @author whm
* @date 2020/11/6 6:17 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class MarkerOptionsBuilder implements MarkerOptionsSink {
final MarkerOptions markerOptions;
MarkerOptionsBuilder() {
this.markerOptions = new MarkerOptions();
}
public MarkerOptions build() {
return markerOptions;
}
@Override
public void setAlpha(float alpha) {
markerOptions.alpha(alpha);
}
@Override
public void setAnchor(float u, float v) {
markerOptions.anchor(u, v);
}
@Override
public void setDraggable(boolean draggable) {
markerOptions.draggable(draggable);
}
@Override
public void setFlat(boolean flat) {
markerOptions.setFlat(flat);
}
@Override
public void setIcon(BitmapDescriptor bitmapDescriptor) {
markerOptions.icon(bitmapDescriptor);
}
@Override
public void setTitle(String title) {
markerOptions.title(title);
}
@Override
public void setSnippet(String snippet) {
markerOptions.snippet(snippet);
}
@Override
public void setPosition(LatLng position) {
markerOptions.position(position);
}
@Override
public void setRotation(float rotation) {
markerOptions.rotateAngle(rotation);
}
@Override
public void setVisible(boolean visible) {
markerOptions.visible(visible);
}
@Override
public void setZIndex(float zIndex) {
markerOptions.zIndex(zIndex);
}
@Override
public void setInfoWindowEnable(boolean enable) {
markerOptions.infoWindowEnable(enable);
}
@Override
public void setClickable(boolean clickable) {
}
}
package com.amap.flutter.map.overlays.marker;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
/**
* @author whm
* @date 2020/11/6 6:12 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public interface MarkerOptionsSink {
void setAlpha(float alpha);
void setAnchor(float u, float v);
void setDraggable(boolean draggable);
void setFlat(boolean flat);
void setIcon(BitmapDescriptor bitmapDescriptor);
void setTitle(String title);
void setSnippet(String snippet);
void setPosition(LatLng position);
void setRotation(float rotation);
void setVisible(boolean visible);
void setZIndex(float zIndex);
void setInfoWindowEnable(boolean enable);
void setClickable(boolean clickable);
}
package com.amap.flutter.map.overlays.marker;
import android.text.TextUtils;
import com.amap.flutter.map.overlays.marker.MarkerOptionsSink;
import com.amap.flutter.map.utils.ConvertUtil;
import java.util.List;
import java.util.Map;
/**
* @author whm
* @date 2020/11/6 8:06 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class MarkerUtil {
public static String interpretMarkerOptions(Object o, MarkerOptionsSink sink) {
if (null == o) {
return null;
}
final Map<?, ?> data = ConvertUtil.toMap(o);
final Object alpha = data.get("alpha");
if (alpha != null) {
sink.setAlpha(ConvertUtil.toFloat(alpha));
}
final Object anchor = data.get("anchor");
if (anchor != null) {
final List<?> anchorData = ConvertUtil.toList(anchor);
sink.setAnchor(ConvertUtil.toFloat(anchorData.get(0)), ConvertUtil.toFloat(anchorData.get(1)));
}
final Object consumeTapEvents = data.get("consumeTapEvents");
final Object draggable = data.get("draggable");
if (draggable != null) {
sink.setDraggable(ConvertUtil.toBoolean(draggable));
}
final Object flat = data.get("flat");
if (flat != null) {
sink.setFlat(ConvertUtil.toBoolean(flat));
}
final Object icon = data.get("icon");
if (icon != null) {
sink.setIcon(ConvertUtil.toBitmapDescriptor(icon));
}
final Object infoWindow = data.get("infoWindow");
if (infoWindow != null) {
interpretInfoWindowOptions(sink, (Map<String, Object>) infoWindow);
}
final Object position = data.get("position");
if (position != null) {
sink.setPosition(ConvertUtil.toLatLng(position));
}
final Object rotation = data.get("rotation");
if (rotation != null) {
sink.setRotation(Math.abs(360- ConvertUtil.toFloat(rotation)));
}
final Object visible = data.get("visible");
if (visible != null) {
sink.setVisible(ConvertUtil.toBoolean(visible));
}
final Object zIndex = data.get("zIndex");
if (zIndex != null) {
sink.setZIndex(ConvertUtil.toFloat(zIndex));
}
final Object infoWindowEnable = data.get("infoWindowEnable");
if(infoWindowEnable != null) {
sink.setInfoWindowEnable(ConvertUtil.toBoolean(infoWindowEnable));
}
final Object clickable = data.get("clickable");
if (null != clickable) {
sink.setClickable(ConvertUtil.toBoolean(clickable));
}
final String markerId = (String) data.get("id");
if (markerId == null) {
throw new IllegalArgumentException("markerId was null");
} else {
return markerId;
}
}
private static void interpretInfoWindowOptions(
MarkerOptionsSink sink, Map<String, Object> infoWindow) {
String title = (String) infoWindow.get("title");
String snippet = (String) infoWindow.get("snippet");
// snippet is nullable.
if (!TextUtils.isEmpty(title)) {
sink.setTitle(title);
}
if (!TextUtils.isEmpty(snippet)) {
sink.setSnippet(snippet);
}
}
}
package com.amap.flutter.map.overlays.marker;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Marker;
import com.amap.api.maps.model.MarkerOptions;
import com.amap.api.maps.model.Poi;
import com.amap.api.maps.model.Polyline;
import com.amap.flutter.map.MyMethodCallHandler;
import com.amap.flutter.map.overlays.AbstractOverlayController;
import com.amap.flutter.map.utils.Const;
import com.amap.flutter.map.utils.ConvertUtil;
import com.amap.flutter.map.utils.LogUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/6 5:38 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class MarkersController
extends AbstractOverlayController<MarkerController>
implements MyMethodCallHandler,
AMap.OnMapClickListener,
AMap.OnMarkerClickListener,
AMap.OnMarkerDragListener,
AMap.OnPOIClickListener {
private static final String CLASS_NAME = "MarkersController";
private String selectedMarkerDartId;
public MarkersController(MethodChannel methodChannel, AMap amap) {
super(methodChannel, amap);
amap.addOnMarkerClickListener(this);
amap.addOnMarkerDragListener(this);
amap.addOnMapClickListener(this);
amap.addOnPOIClickListener(this);
}
@Override
public String[] getRegisterMethodIdArray() {
return Const.METHOD_ID_LIST_FOR_MARKER;
}
@Override
public void doMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
LogUtil.i(CLASS_NAME, "doMethodCall===>" + call.method);
switch (call.method) {
case Const.METHOD_MARKER_UPDATE:
invokeMarkerOptions(call, result);
break;
case Const.METHOD_MARKER_SHOW_INFO_WINDOW:
final String markerId = call.argument("markerId");
showInfoWindow(markerId);
result.success(null);
break;
case Const.METHOD_MARKER_HIDE_INFO_WINDOW:
hideInfoWindow();
result.success(null);
break;
}
}
/**
* 展示 InfoWindow
*/
private void showInfoWindow(String dartMarkerId) {
selectedMarkerDartId = dartMarkerId;
showMarkerInfoWindow(dartMarkerId);
LogUtil.i(CLASS_NAME, "showInfoWindow==>" + dartMarkerId);
}
/**
* 隐藏 InfoWindow
*/
private void hideInfoWindow() {
showMarkerInfoWindow(selectedMarkerDartId);
LogUtil.i(CLASS_NAME, "hideInfoWindow==>" + selectedMarkerDartId);
}
/**
* 执行主动方法更新marker
*
* @param methodCall
* @param result
*/
public void invokeMarkerOptions(MethodCall methodCall, MethodChannel.Result result) {
if (null == methodCall) {
return;
}
Object markersToAdd = methodCall.argument("markersToAdd");
addByList((List<Object>) markersToAdd);
Object markersToChange = methodCall.argument("markersToChange");
updateByList((List<Object>) markersToChange);
Object markerIdsToRemove = methodCall.argument("markerIdsToRemove");
removeByIdList((List<Object>) markerIdsToRemove);
result.success(null);
}
public void addByList(List<Object> markersToAdd) {
if (markersToAdd != null) {
for (Object markerToAdd : markersToAdd) {
add(markerToAdd);
}
}
}
private void add(Object markerObj) {
if (null != amap) {
MarkerOptionsBuilder builder = new MarkerOptionsBuilder();
String dartMarkerId = MarkerUtil.interpretMarkerOptions(markerObj, builder);
if (!TextUtils.isEmpty(dartMarkerId)) {
MarkerOptions markerOptions = builder.build();
final Marker marker = amap.addMarker(markerOptions);
Object clickable = ConvertUtil.getKeyValueFromMapObject(markerObj, "clickable");
if (null != clickable) {
marker.setClickable(ConvertUtil.toBoolean(clickable));
}
MarkerController markerController = new MarkerController(marker);
controllerMapByDartId.put(dartMarkerId, markerController);
idMapByOverlyId.put(marker.getId(), dartMarkerId);
}
}
}
private void updateByList(List<Object> markersToChange) {
if (markersToChange != null) {
for (Object markerToChange : markersToChange) {
update(markerToChange);
}
}
}
private void update(Object markerToChange) {
Object dartMarkerId = ConvertUtil.getKeyValueFromMapObject(markerToChange, "id");
if (null != dartMarkerId) {
MarkerController markerController = controllerMapByDartId.get(dartMarkerId);
if (null != markerController) {
MarkerUtil.interpretMarkerOptions(markerToChange, markerController);
}
}
}
private void removeByIdList(List<Object> markerIdsToRemove) {
if (markerIdsToRemove == null) {
return;
}
for (Object rawMarkerId : markerIdsToRemove) {
if (rawMarkerId == null) {
continue;
}
String markerId = (String) rawMarkerId;
final MarkerController markerController = controllerMapByDartId.remove(markerId);
if (markerController != null) {
idMapByOverlyId.remove(markerController.getMarkerId());
markerController.remove();
}
}
}
private void showMarkerInfoWindow(String dartMarkId) {
MarkerController markerController = controllerMapByDartId.get(dartMarkId);
if (null != markerController) {
markerController.showInfoWindow();
}
}
private void hideMarkerInfoWindow(String dartMarkId, LatLng newPosition) {
if (TextUtils.isEmpty(dartMarkId)) {
return;
}
if (!controllerMapByDartId.containsKey(dartMarkId)) {
return;
}
MarkerController markerController = controllerMapByDartId.get(dartMarkId);
if (null != markerController) {
if (null != newPosition && null != markerController.getPosition()) {
if (markerController.getPosition().equals(newPosition)) {
return;
}
}
markerController.hideInfoWindow();
}
}
@Override
public void onMapClick(LatLng latLng) {
hideMarkerInfoWindow(selectedMarkerDartId, null);
}
@Override
public boolean onMarkerClick(Marker marker) {
String dartId = idMapByOverlyId.get(marker.getId());
if (null == dartId) {
return false;
}
final Map<String, Object> data = new HashMap<>(1);
data.put("markerId", dartId);
selectedMarkerDartId = dartId;
showMarkerInfoWindow(dartId);
methodChannel.invokeMethod("marker#onTap", data);
LogUtil.i(CLASS_NAME, "onMarkerClick==>" + data);
return true;
}
@Override
public void onMarkerDragStart(Marker marker) {
}
@Override
public void onMarkerDrag(Marker marker) {
}
@Override
public void onMarkerDragEnd(Marker marker) {
String markerId = marker.getId();
String dartId = idMapByOverlyId.get(markerId);
LatLng latLng = marker.getPosition();
if (null == dartId) {
return;
}
final Map<String, Object> data = new HashMap<>(2);
data.put("markerId", dartId);
data.put("position", ConvertUtil.latLngToList(latLng));
methodChannel.invokeMethod("marker#onDragEnd", data);
LogUtil.i(CLASS_NAME, "onMarkerDragEnd==>" + data);
}
@Override
public void onPOIClick(Poi poi) {
hideMarkerInfoWindow(selectedMarkerDartId, null != poi ? poi.getCoordinate() : null);
}
}
package com.amap.flutter.map.overlays.polygon;
import com.amap.api.maps.model.AMapPara;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import java.util.List;
/**
* @author whm
* @date 2020/11/12 9:52 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolygonController implements PolygonOptionsSink{
private final Polygon polygon;
private final String id;
PolygonController(Polygon polygon){
this.polygon = polygon;
this.id = polygon.getId();
}
public String getId() {
return id;
}
public void remove() {
polygon.remove();
}
@Override
public void setPoints(List<LatLng> points) {
polygon.setPoints(points);
}
@Override
public void setStrokeWidth(float strokeWidth) {
polygon.setStrokeWidth(strokeWidth);
}
@Override
public void setStrokeColor(int color) {
polygon.setStrokeColor(color);
}
@Override
public void setFillColor(int color) {
polygon.setFillColor(color);
}
@Override
public void setVisible(boolean visible) {
polygon.setVisible(visible);
}
@Override
public void setLineJoinType(AMapPara.LineJoinType joinType) {
//不支持动态修改
}
}
package com.amap.flutter.map.overlays.polygon;
import com.amap.api.maps.model.AMapPara;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.flutter.map.overlays.polyline.PolylineOptionsSink;
import java.util.List;
/**
* @author whm
* @date 2020/11/12 9:51 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolygonOptionsBuilder implements PolygonOptionsSink {
final PolygonOptions polygonOptions;
PolygonOptionsBuilder() {
polygonOptions = new PolygonOptions();
//必须设置为true,否则会出现线条转折处出现断裂的现象
polygonOptions.usePolylineStroke(true);
}
public PolygonOptions build(){
return polygonOptions;
}
@Override
public void setPoints(List<LatLng> points) {
polygonOptions.setPoints(points);
}
@Override
public void setStrokeWidth(float strokeWidth) {
polygonOptions.strokeWidth(strokeWidth);
}
@Override
public void setStrokeColor(int color) {
polygonOptions.strokeColor(color);
}
@Override
public void setFillColor(int color) {
polygonOptions.fillColor(color);
}
@Override
public void setVisible(boolean visible) {
polygonOptions.visible(visible);
}
@Override
public void setLineJoinType(AMapPara.LineJoinType joinType) {
polygonOptions.lineJoinType(joinType);
}
}
package com.amap.flutter.map.overlays.polygon;
import com.amap.api.maps.model.AMapPara;
import com.amap.api.maps.model.LatLng;
import java.util.List;
/**
* @author whm
* @date 2020/11/12 9:52 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
interface PolygonOptionsSink {
//多边形坐标点列表
void setPoints(List<LatLng> points);
//边框宽度
void setStrokeWidth(float strokeWidth);
//边框颜色
void setStrokeColor(int color);
//填充颜色
void setFillColor(int color);
//是否显示
void setVisible(boolean visible);
//边框连接类型
void setLineJoinType(AMapPara.LineJoinType joinType);
}
package com.amap.flutter.map.overlays.polygon;
import com.amap.api.maps.model.AMapPara;
import com.amap.flutter.map.overlays.polyline.PolylineOptionsSink;
import com.amap.flutter.map.utils.ConvertUtil;
import java.util.Map;
/**
* @author whm
* @date 2020/11/12 10:11 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolygonUtil {
static String interpretOptions(Object o, PolygonOptionsSink sink) {
final Map<?, ?> data = ConvertUtil.toMap(o);
final Object points = data.get("points");
if (points != null) {
sink.setPoints(ConvertUtil.toPoints(points));
}
final Object width = data.get("strokeWidth");
if (width != null) {
sink.setStrokeWidth(ConvertUtil.toFloatPixels(width));
}
final Object strokeColor = data.get("strokeColor");
if (strokeColor != null) {
sink.setStrokeColor(ConvertUtil.toInt(strokeColor));
}
final Object fillColor = data.get("fillColor");
if (fillColor != null) {
sink.setFillColor(ConvertUtil.toInt(fillColor));
}
final Object visible = data.get("visible");
if (visible != null) {
sink.setVisible(ConvertUtil.toBoolean(visible));
}
final Object joinType = data.get("joinType");
if (joinType != null) {
sink.setLineJoinType(AMapPara.LineJoinType.valueOf(ConvertUtil.toInt(joinType)));
}
final String polylineId = (String) data.get("id");
if (polylineId == null) {
throw new IllegalArgumentException("polylineId was null");
} else {
return polylineId;
}
}
}
package com.amap.flutter.map.overlays.polygon;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.model.Polygon;
import com.amap.api.maps.model.PolygonOptions;
import com.amap.flutter.map.MyMethodCallHandler;
import com.amap.flutter.map.overlays.AbstractOverlayController;
import com.amap.flutter.map.utils.Const;
import com.amap.flutter.map.utils.ConvertUtil;
import com.amap.flutter.map.utils.LogUtil;
import java.util.List;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/12 9:53 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class PolygonsController
extends AbstractOverlayController<PolygonController>
implements MyMethodCallHandler {
private static final String CLASS_NAME = "PolygonsController";
public PolygonsController(MethodChannel methodChannel, AMap amap) {
super(methodChannel, amap);
}
@Override
public void doMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
String methodId = call.method;
LogUtil.i(CLASS_NAME, "doMethodCall===>" +methodId);
switch (methodId) {
case Const.METHOD_POLYGON_UPDATE:
invokePolylineOptions(call, result);
break;
}
}
@Override
public String[] getRegisterMethodIdArray() {
return Const.METHOD_ID_LIST_FOR_POLYGON;
}
/**
*
* @param methodCall
* @param result
*/
public void invokePolylineOptions(MethodCall methodCall, MethodChannel.Result result) {
if (null == methodCall) {
return;
}
Object listToAdd = methodCall.argument("polygonsToAdd");
addByList((List<Object>) listToAdd);
Object listToChange = methodCall.argument("polygonsToChange");
updateByList((List<Object>) listToChange);
Object listIdToRemove = methodCall.argument("polygonIdsToRemove");
removeByIdList((List<Object>) listIdToRemove);
result.success(null);
}
public void addByList(List<Object> polygonsToAdd) {
if (polygonsToAdd != null) {
for (Object polygonToAdd : polygonsToAdd) {
add(polygonToAdd);
}
}
}
private void add(Object polylineObj) {
if (null != amap) {
PolygonOptionsBuilder builder = new PolygonOptionsBuilder();
String dartId = PolygonUtil.interpretOptions(polylineObj, builder);
if (!TextUtils.isEmpty(dartId)) {
PolygonOptions options = builder.build();
final Polygon polygon = amap.addPolygon(options);
PolygonController polygonController = new PolygonController(polygon);
controllerMapByDartId.put(dartId, polygonController);
idMapByOverlyId.put(polygon.getId(), dartId);
}
}
}
private void updateByList(List<Object> overlaysToChange) {
if (overlaysToChange != null) {
for (Object overlayToChange : overlaysToChange) {
update(overlayToChange);
}
}
}
private void update(Object toUpdate) {
Object dartId = ConvertUtil.getKeyValueFromMapObject(toUpdate, "id");
if (null != dartId) {
PolygonController controller = controllerMapByDartId.get(dartId);
if (null != controller) {
PolygonUtil.interpretOptions(toUpdate, controller);
}
}
}
private void removeByIdList(List<Object> toRemoveIdList) {
if (toRemoveIdList == null) {
return;
}
for (Object toRemoveId : toRemoveIdList) {
if (toRemoveId == null) {
continue;
}
String dartId = (String) toRemoveId;
final PolygonController controller = controllerMapByDartId.remove(dartId);
if (controller != null) {
idMapByOverlyId.remove(controller.getId());
controller.remove();
}
}
}
}
package com.amap.flutter.map.overlays.polyline;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import java.util.List;
/**
* @author whm
* @date 2020/11/10 2:58 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolylineController implements PolylineOptionsSink {
final Polyline polyline;
final String polylineId;
PolylineController(Polyline polyline) {
this.polyline = polyline;
this.polylineId = polyline.getId();
}
public String getPolylineId() {
return polylineId;
}
public void remove() {
if(null != polyline) {
polyline.remove();
}
}
@Override
public void setPoints(List<LatLng> points) {
polyline.setPoints(points);
}
@Override
public void setWidth(float width) {
polyline.setWidth(width);
}
@Override
public void setColor(int color) {
polyline.setColor(color);
}
@Override
public void setVisible(boolean visible) {
polyline.setVisible(visible);
}
@Override
public void setCustomTexture(BitmapDescriptor customTexture) {
polyline.setCustomTexture(customTexture);
}
@Override
public void setCustomTextureList(List<BitmapDescriptor> customTextureList) {
polyline.setCustomTextureList(customTextureList);
}
@Override
public void setColorList(List<Integer> colorList) {
PolylineOptions options = polyline.getOptions();
options.colorValues(colorList);
polyline.setOptions(options);
}
@Override
public void setCustomIndexList(List<Integer> customIndexList) {
PolylineOptions options = polyline.getOptions();
options.setCustomTextureIndex(customIndexList);
polyline.setOptions(options);
}
@Override
public void setGeodesic(boolean geodesic) {
polyline.setGeodesic(geodesic);
}
@Override
public void setGradient(boolean gradient) {
polyline.setGeodesic(gradient);
}
@Override
public void setAlpha(float alpha) {
polyline.setTransparency(alpha);
}
@Override
public void setDashLineType(int type) {
PolylineOptions options = polyline.getOptions();
options.setDottedLineType(type);
polyline.setOptions(options);
}
@Override
public void setDashLine(boolean dashLine) {
polyline.setDottedLine(dashLine);
}
@Override
public void setLineCapType(PolylineOptions.LineCapType lineCapType) {
PolylineOptions options = polyline.getOptions();
options.lineCapType(lineCapType);
polyline.setOptions(options);
}
@Override
public void setLineJoinType(PolylineOptions.LineJoinType joinType) {
PolylineOptions options = polyline.getOptions();
options.lineJoinType(joinType);
polyline.setOptions(options);
}
}
package com.amap.flutter.map.overlays.polyline;
import com.amap.api.maps.model.AMapPara;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.PolylineOptions;
import java.util.List;
/**
* @author whm
* @date 2020/11/10 2:57 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolylineOptionsBuilder implements PolylineOptionsSink {
final PolylineOptions polylineOptions;
PolylineOptionsBuilder() {
polylineOptions = new PolylineOptions();
}
@Override
public void setPoints(List<LatLng> points) {
polylineOptions.setPoints(points);
}
@Override
public void setWidth(float width) {
polylineOptions.width(width);
}
@Override
public void setColor(int color) {
polylineOptions.color(color);
}
@Override
public void setVisible(boolean visible) {
polylineOptions.visible(visible);
}
@Override
public void setCustomTexture(BitmapDescriptor customTexture) {
polylineOptions.setCustomTexture(customTexture);
}
@Override
public void setCustomTextureList(List<BitmapDescriptor> customTextureList) {
polylineOptions.setCustomTextureList(customTextureList);
}
@Override
public void setColorList(List<Integer> colorList) {
polylineOptions.colorValues(colorList);
}
@Override
public void setCustomIndexList(List<Integer> customIndexList) {
polylineOptions.setCustomTextureIndex(customIndexList);
}
@Override
public void setGeodesic(boolean geodesic) {
polylineOptions.geodesic(geodesic);
}
@Override
public void setGradient(boolean gradient) {
polylineOptions.useGradient(gradient);
}
@Override
public void setAlpha(float alpha) {
polylineOptions.transparency(alpha);
}
@Override
public void setDashLineType(int type) {
polylineOptions.setDottedLineType(type);
}
@Override
public void setDashLine(boolean dashLine) {
polylineOptions.setDottedLine(dashLine);
}
@Override
public void setLineCapType(PolylineOptions.LineCapType lineCapType) {
polylineOptions.lineCapType(lineCapType);
}
@Override
public void setLineJoinType(PolylineOptions.LineJoinType joinType) {
polylineOptions.lineJoinType(joinType);
}
public PolylineOptions build(){
return polylineOptions;
}
}
package com.amap.flutter.map.overlays.polyline;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.PolylineOptions;
import java.util.List;
/**
* @author whm
* @date 2020/11/10 2:58 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public interface PolylineOptionsSink {
//路线点
void setPoints(List<LatLng> points);
//宽度
void setWidth(float width);
//颜色
void setColor(int color);
//是否显示
void setVisible(boolean visible);
//纹理
void setCustomTexture(BitmapDescriptor customTexture);
//纹理列表
void setCustomTextureList(List<BitmapDescriptor> customTextureList);
//颜色列表
void setColorList(List<Integer> colorList);
//纹理顺序
void setCustomIndexList(List<Integer> customIndexList);
//是否大地曲线
void setGeodesic(boolean geodesic);
//是否渐变
void setGradient(boolean gradient);
//透明度
void setAlpha(float alpha);
//虚线类型
void setDashLineType(int type);
//是否虚线
void setDashLine(boolean dashLine);
//线冒类型
void setLineCapType(PolylineOptions.LineCapType lineCapType);
//线交接类型
void setLineJoinType(PolylineOptions.LineJoinType joinType);
}
package com.amap.flutter.map.overlays.polyline;
import android.text.TextUtils;
import android.util.Log;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.flutter.map.utils.ConvertUtil;
import java.util.List;
import java.util.Map;
/**
* @author whm
* @date 2020/11/10 4:34 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
class PolylineUtil {
private static final String CLASS_NAME = "PolylineUtil";
//虚线类型
private static final int[] DASH_LINE_TYPE = {-1,0,1};
static String interpretOptions(Object o, PolylineOptionsSink sink) {
final Map<?, ?> data = ConvertUtil.toMap(o);
final Object points = data.get("points");
if (points != null) {
sink.setPoints(ConvertUtil.toPoints(points));
}
final Object width = data.get("width");
if (width != null) {
sink.setWidth(ConvertUtil.toFloatPixels(width));
}
final Object visible = data.get("visible");
if (visible != null) {
sink.setVisible(ConvertUtil.toBoolean(visible));
}
final Object geodesic = data.get("geodesic");
if (geodesic != null) {
sink.setGeodesic(ConvertUtil.toBoolean(geodesic));
}
final Object gradient = data.get("gradient");
if (gradient != null) {
sink.setGradient(ConvertUtil.toBoolean(gradient));
}
final Object alpha = data.get("alpha");
if (alpha != null) {
sink.setAlpha(ConvertUtil.toFloat(alpha));
}
final Object dashLineType = data.get("dashLineType");
if (dashLineType != null) {
int rawType = ConvertUtil.toInt(dashLineType);
if (rawType > DASH_LINE_TYPE.length) {
rawType = 0;
}
if(DASH_LINE_TYPE[rawType] == -1) {
sink.setDashLine(false);
} else {
sink.setDashLine(true);
sink.setDashLineType(DASH_LINE_TYPE[rawType]);
}
}
final Object capType = data.get("capType");
if (capType != null) {
sink.setLineCapType(PolylineOptions.LineCapType.valueOf(ConvertUtil.toInt(capType)));
}
final Object joinType = data.get("joinType");
if (joinType != null) {
sink.setLineJoinType(PolylineOptions.LineJoinType.valueOf(ConvertUtil.toInt(joinType)));
}
final Object customTexture = data.get("customTexture");
if (customTexture != null) {
sink.setCustomTexture(ConvertUtil.toBitmapDescriptor(customTexture));
}
final Object customTextureList = data.get("customTextureList");
if (customTextureList != null) {
sink.setCustomTextureList(ConvertUtil.toBitmapDescriptorList(customTextureList));
}
final Object color = data.get("color");
if (color != null) {
sink.setColor(ConvertUtil.toInt(color));
}
final Object colorList = data.get("colorList");
if (colorList != null) {
sink.setColorList((List<Integer>) ConvertUtil.toList(colorList));
}
final String dartId = (String) data.get("id");
if(TextUtils.isEmpty(dartId)) {
Log.w(CLASS_NAME, "没有传入正确的dart层ID, 请确认对应的key值是否正确!!!");
}
return dartId;
}
}
package com.amap.flutter.map.overlays.polyline;
import android.text.TextUtils;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.model.Polyline;
import com.amap.api.maps.model.PolylineOptions;
import com.amap.flutter.map.MyMethodCallHandler;
import com.amap.flutter.map.overlays.AbstractOverlayController;
import com.amap.flutter.map.utils.Const;
import com.amap.flutter.map.utils.ConvertUtil;
import com.amap.flutter.map.utils.LogUtil;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/10 2:58 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class PolylinesController
extends AbstractOverlayController<PolylineController>
implements MyMethodCallHandler,
AMap.OnPolylineClickListener {
private static final String CLASS_NAME = "PolylinesController";
public PolylinesController(MethodChannel methodChannel, AMap amap) {
super(methodChannel, amap);
amap.addOnPolylineClickListener(this);
}
@Override
public String[] getRegisterMethodIdArray() {
return Const.METHOD_ID_LIST_FOR_POLYLINE;
}
@Override
public void doMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
LogUtil.i(CLASS_NAME, "doMethodCall===>" + call.method);
String methodStr = call.method;
switch (methodStr) {
case Const.METHOD_POLYLINE_UPDATE:
invokePolylineOptions(call, result);
break;
}
}
@Override
public void onPolylineClick(Polyline polyline) {
String dartId = idMapByOverlyId.get(polyline.getId());
if (null == dartId) {
return;
}
final Map<String, Object> data = new HashMap<>(1);
data.put("polylineId", dartId);
methodChannel.invokeMethod("polyline#onTap", data);
LogUtil.i(CLASS_NAME, "onPolylineClick==>" + data);
}
/**
*
* @param methodCall
* @param result
*/
private void invokePolylineOptions(MethodCall methodCall, MethodChannel.Result result) {
if (null == methodCall) {
return;
}
Object listToAdd = methodCall.argument("polylinesToAdd");
addByList((List<Object>) listToAdd);
Object listToChange = methodCall.argument("polylinesToChange");
updateByList((List<Object>) listToChange);
Object polylineIdsToRemove = methodCall.argument("polylineIdsToRemove");
removeByIdList((List<Object>) polylineIdsToRemove);
result.success(null);
}
public void addByList(List<Object> polylinesToAdd) {
if (polylinesToAdd != null) {
for (Object markerToAdd : polylinesToAdd) {
addPolyline(markerToAdd);
}
}
}
private void addPolyline(Object polylineObj) {
if (null != amap) {
PolylineOptionsBuilder builder = new PolylineOptionsBuilder();
String dartId = PolylineUtil.interpretOptions(polylineObj, builder);
if (!TextUtils.isEmpty(dartId)) {
PolylineOptions polylineOptions = builder.build();
final Polyline polyline = amap.addPolyline(polylineOptions);
PolylineController polylineController = new PolylineController(polyline);
controllerMapByDartId.put(dartId, polylineController);
idMapByOverlyId.put(polyline.getId(), dartId);
}
}
}
private void updateByList(List<Object> polylineToChange) {
if (polylineToChange != null) {
for (Object markerToChange : polylineToChange) {
update(markerToChange);
}
}
}
private void update(Object polylineToChange) {
Object polylineId = ConvertUtil.getKeyValueFromMapObject(polylineToChange, "id");
if (null != polylineId) {
PolylineController polylineController = controllerMapByDartId.get(polylineId);
if (null != polylineController) {
PolylineUtil.interpretOptions(polylineToChange, polylineController);
}
}
}
private void removeByIdList(List<Object> polylineIdsToRemove) {
if (polylineIdsToRemove == null) {
return;
}
for (Object rawPolylineId : polylineIdsToRemove) {
if (rawPolylineId == null) {
continue;
}
String markerId = (String) rawPolylineId;
final PolylineController polylineController = controllerMapByDartId.remove(markerId);
if (polylineController != null) {
idMapByOverlyId.remove(polylineController.getPolylineId());
polylineController.remove();
}
}
}
}
package com.amap.flutter.map.utils;
/**
* @author whm
* @date 2020/11/10 9:44 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class Const {
/**
* map
*/
public static final String METHOD_MAP_WAIT_FOR_MAP = "map#waitForMap";
public static final String METHOD_MAP_CONTENT_APPROVAL_NUMBER = "map#contentApprovalNumber";
public static final String METHOD_MAP_VISIBLE_REGION = "map#visibleRegion";
public static final String METHOD_MAP_SATELLITE_IMAGE_APPROVAL_NUMBER = "map#satelliteImageApprovalNumber";
public static final String METHOD_MAP_UPDATE = "map#update";
public static final String METHOD_MAP_MOVE_CAMERA = "camera#move";
public static final String METHOD_MAP_SEARCH_POI = "camera#searchPOI";
public static final String METHOD_MAP_SEARCH_INPUT = "camera#searchInput";
public static final String METHOD_MAP_SEARCH_REGEOCODE = "camera#searchRegeocode";
public static final String METHOD_MAP_SET_RENDER_FPS = "map#setRenderFps";
public static final String METHOD_MAP_TAKE_SNAPSHOT = "map#takeSnapshot";
public static final String METHOD_MAP_CLEAR_DISK = "map#clearDisk";
public static final String[] METHOD_ID_LIST_FOR_MAP = {
METHOD_MAP_CONTENT_APPROVAL_NUMBER,
METHOD_MAP_SATELLITE_IMAGE_APPROVAL_NUMBER,
METHOD_MAP_WAIT_FOR_MAP,
METHOD_MAP_UPDATE,
METHOD_MAP_MOVE_CAMERA,
METHOD_MAP_SET_RENDER_FPS,
METHOD_MAP_TAKE_SNAPSHOT,
METHOD_MAP_SEARCH_POI,
METHOD_MAP_SEARCH_INPUT,
METHOD_MAP_SEARCH_REGEOCODE,
METHOD_MAP_VISIBLE_REGION,
METHOD_MAP_CLEAR_DISK};
/**
* markers
*/
public static final String METHOD_MARKER_UPDATE = "markers#update";
public static final String METHOD_MARKER_SHOW_INFO_WINDOW = "markers#showInfoWindow";
public static final String METHOD_MARKER_HIDE_INFO_WINDOW = "markers#hideInfoWindow";
public static final String[] METHOD_ID_LIST_FOR_MARKER = {
METHOD_MARKER_UPDATE,
METHOD_MARKER_HIDE_INFO_WINDOW,
METHOD_MARKER_SHOW_INFO_WINDOW};
/**
* polygons
*/
public static final String METHOD_POLYGON_UPDATE = "polygons#update";
public static final String[] METHOD_ID_LIST_FOR_POLYGON = {METHOD_POLYGON_UPDATE};
/**
* polylines
*/
public static final String METHOD_POLYLINE_UPDATE = "polylines#update";
public static final String[] METHOD_ID_LIST_FOR_POLYLINE = {METHOD_POLYLINE_UPDATE};
}
package com.amap.flutter.map.utils;
import android.util.Log;
/**
* @author whm
* @date 2020/11/6 11:04 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class LogUtil {
public static boolean isDebugMode = false;
private static final String TAG = "AMapFlutter_";
public static void i(String className, String message) {
if(isDebugMode) {
Log.i(TAG+className, message);
}
}
public static void d(String className, String message) {
if(isDebugMode) {
Log.d(TAG+className, message);
}
}
public static void w(String className, String message) {
if(isDebugMode) {
Log.w(TAG+className, message);
}
}
public static void e(String className, String methodName, Throwable e) {
if (isDebugMode) {
Log.e(TAG+className, methodName + " exception!!", e);
}
}
}
# Miscellaneous
*.class
*.log
*.pyc
*.swp
.DS_Store
.atom/
.buildlog/
.history
.svn/
# IntelliJ related
*.iml
*.ipr
*.iws
.idea/
# The .vscode folder contains launch configuration and tasks you configure in
# VS Code which you may wish to be included in version control, so this line
# is commented out by default.
#.vscode/
# Flutter/Dart/Pub related
**/doc/api/
**/ios/Flutter/.last_build_id
.dart_tool/
.flutter-plugins
.flutter-plugins-dependencies
.packages
.pub-cache/
.pub/
/build/
# Web related
lib/generated_plugin_registrant.dart
# Symbolication related
app.*.symbols
# Obfuscation related
app.*.map.json
# This file tracks properties of this Flutter project.
# Used by Flutter tool to assess capabilities and perform upgrades etc.
#
# This file should be version controlled and should not be manually edited.
version:
revision: 84f3d28555368a70270e9ac8390a9441df95e752
channel: stable
project_type: app
# amap_flutter_map_example
Demonstrates how to use the amap_flutter_map plugin.
## Getting Started
This project is a starting point for a Flutter application.
A few resources to get you started if this is your first Flutter project:
- [Lab: Write your first Flutter app](https://flutter.dev/docs/get-started/codelab)
- [Cookbook: Useful Flutter samples](https://flutter.dev/docs/cookbook)
For help getting started with Flutter, view our
[online documentation](https://flutter.dev/docs), which offers tutorials,
samples, guidance on mobile development, and a full API reference.
gradle-wrapper.jar
/.gradle
/captures/
/gradlew
/gradlew.bat
/local.properties
GeneratedPluginRegistrant.java
# Remember to never publicly share your keystore.
# See https://flutter.dev/docs/deployment/android#reference-the-keystore-from-the-app
key.properties
def localProperties = new Properties()
def localPropertiesFile = rootProject.file('local.properties')
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader('UTF-8') { reader ->
localProperties.load(reader)
}
}
def flutterRoot = localProperties.getProperty('flutter.sdk')
if (flutterRoot == null) {
throw new GradleException("Flutter SDK not found. Define location with flutter.sdk in the local.properties file.")
}
def flutterVersionCode = localProperties.getProperty('flutter.versionCode')
if (flutterVersionCode == null) {
flutterVersionCode = '1'
}
def flutterVersionName = localProperties.getProperty('flutter.versionName')
if (flutterVersionName == null) {
flutterVersionName = '1.0'
}
apply plugin: 'com.android.application'
apply from: "$flutterRoot/packages/flutter_tools/gradle/flutter.gradle"
def keystorePropertiesFile = rootProject.file("app/key.properties")
def keystoreProperties = new Properties()
keystoreProperties.load(new FileInputStream(keystorePropertiesFile))
android {
compileSdkVersion 31
lintOptions {
disable 'InvalidPackage'
}
defaultConfig {
// TODO: Specify your own unique Application ID (https://developer.android.com/studio/build/application-id.html).
applicationId "com.amap.flutter.test_map"
minSdkVersion 16
targetSdkVersion 31
versionCode flutterVersionCode.toInteger()
versionName flutterVersionName
}
signingConfigs {
release {
//keystore中key的别名
keyAlias keystoreProperties['keyAlias']
//keystore中key的密码
keyPassword keystoreProperties['keyPassword']
//keystore的文件路径,可以是绝对路径也可以是相对路径
storeFile file(keystoreProperties['storeFile'])
//keystore的密码l
storePassword keystoreProperties['storePassword']
}
}
buildTypes {
debug {
signingConfig signingConfigs.release
}
release {
// flutter build apk
signingConfig signingConfigs.release
}
}
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
}
dependencies {
//demo中引入高德地图SDK
implementation 'com.amap.api:3dmap:8.1.0'
}
flutter {
source '../..'
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amap.flutter.test_map">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amap.flutter.test_map">
<!-- io.flutter.app.FlutterApplication is an android.app.Application that
calls FlutterMain.startInitialization(this); in its onCreate method.
In most cases you can leave this as-is, but you if you want to provide
additional functionality it is fine to subclass or reimplement
FlutterApplication and put your custom class here. -->
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<application
android:name="${applicationName}"
android:label="amap_flutter_map_example"
android:icon="@mipmap/ic_launcher">
<meta-data
android:name="com.amap.api.v2.apikey"
android:value="6a158bd9bdede0d4276a7ab4fc45ca1b" />
<activity
android:name=".MainActivity"
android:launchMode="singleTop"
android:theme="@style/LaunchTheme"
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
to determine the Window background behind the Flutter UI. -->
<meta-data
android:name="io.flutter.embedding.android.NormalTheme"
android:resource="@style/NormalTheme"
/>
<!-- Displays an Android View that continues showing the launch screen
Drawable until Flutter paints its first frame, then this splash
screen fades out. A splash screen is useful to avoid any visual
gap between the end of Android's launch screen and the painting of
Flutter's first frame. -->
<meta-data
android:name="io.flutter.embedding.android.SplashScreenDrawable"
android:resource="@drawable/launch_background"
/>
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<!-- Don't delete the meta-data below.
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
<meta-data
android:name="flutterEmbedding"
android:value="2" />
</application>
</manifest>
package com.amap.flutter.test_map;
import io.flutter.embedding.android.FlutterActivity;
public class MainActivity extends FlutterActivity {
}
<?xml version="1.0" encoding="utf-8"?>
<!-- Modify this file to customize your launch splash screen -->
<layer-list xmlns:android="http://schemas.android.com/apk/res/android">
<item android:drawable="@android:color/white" />
<!-- You can insert your own image assets here -->
<item>
<bitmap
android:gravity="center"
android:src="@mipmap/ic_launcher" />
</item>
</layer-list>
<?xml version="1.0" encoding="utf-8"?>
<resources>
<!-- Theme applied to the Android Window while the process is starting -->
<style name="LaunchTheme" parent="@android:style/Theme.Black.NoTitleBar">
<!-- Show a splash screen on the activity. Automatically removed when
Flutter draws its first frame -->
<item name="android:windowBackground">@drawable/launch_background</item>
</style>
<!-- Theme applied to the Android Window as soon as the process has started.
This theme determines the color of the Android Window while your
Flutter UI initializes, as well as behind your Flutter UI while its
running.
This Theme is only used starting with V2 of Flutter's Android embedding. -->
<style name="NormalTheme" parent="@android:style/Theme.Black.NoTitleBar">
<item name="android:windowBackground">@android:color/white</item>
</style>
</resources>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amap.flutter.test_map">
<!-- Flutter needs it to communicate with the running application
to allow setting breakpoints, to provide hot reload, etc.
-->
<uses-permission android:name="android.permission.INTERNET"/>
</manifest>
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.0'
}
}
allprojects {
repositories {
google()
jcenter()
}
}
rootProject.buildDir = '../build'
subprojects {
project.buildDir = "${rootProject.buildDir}/${project.name}"
}
subprojects {
project.evaluationDependsOn(':app')
}
task clean(type: Delete) {
delete rootProject.buildDir
}
org.gradle.jvmargs=-Xmx1536M
android.useAndroidX=true
android.enableJetifier=true
android.enableR8=true
#Fri Jun 23 08:50:38 CEST 2017
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.2-all.zip
include ':app'
def localPropertiesFile = new File(rootProject.projectDir, "local.properties")
def properties = new Properties()
assert localPropertiesFile.exists()
localPropertiesFile.withReader("UTF-8") { reader -> properties.load(reader) }
def flutterSdkPath = properties.getProperty("flutter.sdk")
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
apply from: "$flutterSdkPath/packages/flutter_tools/gradle/app_plugin_loader.gradle"
*.mode1v3
*.mode2v3
*.moved-aside
*.pbxuser
*.perspectivev3
**/*sync/
.sconsign.dblite
.tags*
**/.vagrant/
**/DerivedData/
Icon?
**/Pods/
**/.symlinks/
profile
xcuserdata
**/.generated/
Flutter/App.framework
Flutter/Flutter.framework
Flutter/Flutter.podspec
Flutter/Generated.xcconfig
Flutter/app.flx
Flutter/app.zip
Flutter/flutter_assets/
Flutter/flutter_export_environment.sh
ServiceDefinitions.json
Runner/GeneratedPluginRegistrant.*
# Exceptions to above rules.
!default.mode1v3
!default.mode2v3
!default.pbxuser
!default.perspectivev3
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>App</string>
<key>CFBundleIdentifier</key>
<string>io.flutter.flutter.app</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>App</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1.0</string>
<key>MinimumOSVersion</key>
<string>9.0</string>
</dict>
</plist>
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"
#include "Generated.xcconfig"
#include "Pods/Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"
#include "Generated.xcconfig"
# Uncomment this line to define a global platform for your project
# platform :ios, '9.0'
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def flutter_root
generated_xcode_build_settings_path = File.expand_path(File.join('..', 'Flutter', 'Generated.xcconfig'), __FILE__)
unless File.exist?(generated_xcode_build_settings_path)
raise "#{generated_xcode_build_settings_path} must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
File.foreach(generated_xcode_build_settings_path) do |line|
matches = line.match(/FLUTTER_ROOT\=(.*)/)
return matches[1].strip if matches
end
raise "FLUTTER_ROOT not found in #{generated_xcode_build_settings_path}. Try deleting Generated.xcconfig, then run flutter pub get"
end
require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelper'), flutter_root)
flutter_ios_podfile_setup
target 'Runner' do
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
end
post_install do |installer|
installer.pods_project.targets.each do |target|
flutter_additional_ios_build_settings(target)
end
end
PODS:
- AMap3DMap (8.1.0):
- AMapFoundation (~> 1.6.9)
- amap_flutter_map (0.0.1):
- AMap3DMap
- AMapSearch
- Flutter
- AMapFoundation (1.6.9)
- AMapSearch (9.2.0):
- AMapFoundation (~> 1.6.9)
- Flutter (1.0.0)
- permission_handler_apple (9.0.4):
- Flutter
DEPENDENCIES:
- amap_flutter_map (from `.symlinks/plugins/amap_flutter_map/ios`)
- Flutter (from `Flutter`)
- permission_handler_apple (from `.symlinks/plugins/permission_handler_apple/ios`)
SPEC REPOS:
trunk:
- AMap3DMap
- AMapFoundation
- AMapSearch
EXTERNAL SOURCES:
amap_flutter_map:
:path: ".symlinks/plugins/amap_flutter_map/ios"
Flutter:
:path: Flutter
permission_handler_apple:
:path: ".symlinks/plugins/permission_handler_apple/ios"
SPEC CHECKSUMS:
AMap3DMap: 135eaaf64a29aeb2f0bca07670db26fbf3271245
amap_flutter_map: f3fe3434a2e11b12a9d0e2194ee6ff5a534702fe
AMapFoundation: 8d8ecbb0b2e9ce5487995360d26c885d94642bfd
AMapSearch: b461cdf25b39cdca8957017de2f376cd1ac5da85
Flutter: 50d75fe2f02b26cc09d224853bb45737f8b3214a
permission_handler_apple: 44366e37eaf29454a1e7b1b7d736c2cceaeb17ce
PODFILE CHECKSUM: 8e679eca47255a8ca8067c4c67aab20e64cb974d
COCOAPODS: 1.10.1
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
差异被折叠。
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论