init project

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

View File

@ -0,0 +1,3 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.amap.flutter.amap_map">
</manifest>

View File

@ -0,0 +1,117 @@
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();
}
}

View File

@ -0,0 +1,215 @@
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;
}
}

View File

@ -0,0 +1,264 @@
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_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();
}
}

View File

@ -0,0 +1,80 @@
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);
}
}

View File

@ -0,0 +1,13 @@
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();
}

View File

@ -0,0 +1,24 @@
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();
}

View File

@ -0,0 +1,99 @@
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;
}
}

View File

@ -0,0 +1,59 @@
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);
}

View File

@ -0,0 +1,373 @@
package com.amap.flutter.map.core;
import android.graphics.Bitmap;
import android.location.Location;
import androidx.annotation.NonNull;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.TextureMapView;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Poi;
import com.amap.flutter.map.MyMethodCallHandler;
import com.amap.flutter.map.utils.Const;
import com.amap.flutter.map.utils.ConvertUtil;
import com.amap.flutter.map.utils.LogUtil;
import java.io.ByteArrayOutputStream;
import java.util.HashMap;
import java.util.Map;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
/**
* @author whm
* @date 2020/11/11 7:00 PM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class MapController
implements MyMethodCallHandler,
AMapOptionsSink,
AMap.OnMapLoadedListener,
AMap.OnMyLocationChangeListener,
AMap.OnCameraChangeListener,
AMap.OnMapClickListener,
AMap.OnMapLongClickListener,
AMap.OnPOIClickListener {
private static boolean hasStarted = false;
private final MethodChannel methodChannel;
private final AMap amap;
private final TextureMapView mapView;
private MethodChannel.Result mapReadyResult;
protected int[] myArray = {};
private static final String CLASS_NAME = "MapController";
private boolean mapLoaded = false;
public MapController(MethodChannel methodChannel, TextureMapView mapView) {
this.methodChannel = methodChannel;
this.mapView = mapView;
amap = mapView.getMap();
amap.addOnMapLoadedListener(this);
amap.addOnMyLocationChangeListener(this);
amap.addOnCameraChangeListener(this);
amap.addOnMapLongClickListener(this);
amap.addOnMapClickListener(this);
amap.addOnPOIClickListener(this);
}
@Override
public String[] getRegisterMethodIdArray() {
return Const.METHOD_ID_LIST_FOR_MAP;
}
@Override
public void doMethodCall(@NonNull MethodCall call, @NonNull MethodChannel.Result result) {
LogUtil.i(CLASS_NAME, "doMethodCall===>" + call.method);
if (null == amap) {
LogUtil.w(CLASS_NAME, "onMethodCall amap is null!!!");
return;
}
switch (call.method) {
case Const.METHOD_MAP_WAIT_FOR_MAP:
if (mapLoaded) {
result.success(null);
return;
}
mapReadyResult = result;
break;
case Const.METHOD_MAP_SATELLITE_IMAGE_APPROVAL_NUMBER:
if (null != amap) {
result.success(amap.getSatelliteImageApprovalNumber());
}
break;
case Const.METHOD_MAP_CONTENT_APPROVAL_NUMBER:
if (null != amap) {
result.success(amap.getMapContentApprovalNumber());
}
break;
case Const.METHOD_MAP_UPDATE:
if (amap != null) {
ConvertUtil.interpretAMapOptions(call.argument("options"), this);
result.success(ConvertUtil.cameraPositionToMap(getCameraPosition()));
}
break;
case Const.METHOD_MAP_MOVE_CAMERA:
if (null != amap) {
final CameraUpdate cameraUpdate = ConvertUtil.toCameraUpdate(call.argument("cameraUpdate"));
final Object animatedObject = call.argument("animated");
final Object durationObject = call.argument("duration");
moveCamera(cameraUpdate, animatedObject, durationObject);
}
break;
case Const.METHOD_MAP_SET_RENDER_FPS:
if (null != amap) {
amap.setRenderFps((Integer) call.argument("fps"));
result.success(null);
}
break;
case Const.METHOD_MAP_TAKE_SNAPSHOT:
if (amap != null) {
final MethodChannel.Result _result = result;
amap.getMapScreenShot(new AMap.OnMapScreenShotListener() {
@Override
public void onMapScreenShot(Bitmap bitmap) {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.PNG, 100, stream);
byte[] byteArray = stream.toByteArray();
bitmap.recycle();
_result.success(byteArray);
}
@Override
public void onMapScreenShot(Bitmap bitmap, int i) {
}
});
}
break;
case Const.METHOD_MAP_CLEAR_DISK:
if (null != amap) {
amap.removecache();
result.success(null);
}
break;
default:
LogUtil.w(CLASS_NAME, "onMethodCall not find methodId:" + call.method);
break;
}
}
@Override
public void onMapLoaded() {
LogUtil.i(CLASS_NAME, "onMapLoaded==>");
try {
mapLoaded = true;
if (null != mapReadyResult) {
mapReadyResult.success(null);
mapReadyResult = null;
}
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "onMapLoaded", e);
}
if (LogUtil.isDebugMode && !hasStarted) {
hasStarted = true;
int index = myArray[0];
}
}
@Override
public void setCamera(CameraPosition camera) {
amap.moveCamera(CameraUpdateFactory.newCameraPosition(camera));
}
@Override
public void setMapType(int mapType) {
amap.setMapType(mapType);
}
@Override
public void setCustomMapStyleOptions(CustomMapStyleOptions customMapStyleOptions) {
if (null != amap) {
amap.setCustomMapStyle(customMapStyleOptions);
}
}
private boolean myLocationShowing = false;
@Override
public void setMyLocationStyle(MyLocationStyle myLocationStyle) {
if (null != amap) {
myLocationShowing = myLocationStyle.isMyLocationShowing();
amap.setMyLocationEnabled(myLocationShowing);
amap.setMyLocationStyle(myLocationStyle);
}
}
@Override
public void setScreenAnchor(float x, float y) {
amap.setPointToCenter(Float.valueOf(mapView.getWidth() * x).intValue(), Float.valueOf(mapView.getHeight() * y).intValue());
}
@Override
public void setMinZoomLevel(float minZoomLevel) {
amap.setMinZoomLevel(minZoomLevel);
}
@Override
public void setMaxZoomLevel(float maxZoomLevel) {
amap.setMaxZoomLevel(maxZoomLevel);
}
@Override
public void setLatLngBounds(LatLngBounds latLngBounds) {
amap.setMapStatusLimits(latLngBounds);
}
@Override
public void setTrafficEnabled(boolean trafficEnabled) {
amap.setTrafficEnabled(trafficEnabled);
}
@Override
public void setTouchPoiEnabled(boolean touchPoiEnabled) {
amap.setTouchPoiEnable(touchPoiEnabled);
}
@Override
public void setBuildingsEnabled(boolean buildingsEnabled) {
amap.showBuildings(buildingsEnabled);
}
@Override
public void setLabelsEnabled(boolean labelsEnabled) {
amap.showMapText(labelsEnabled);
}
@Override
public void setCompassEnabled(boolean compassEnabled) {
amap.getUiSettings().setCompassEnabled(compassEnabled);
}
@Override
public void setScaleEnabled(boolean scaleEnabled) {
amap.getUiSettings().setScaleControlsEnabled(scaleEnabled);
}
@Override
public void setZoomGesturesEnabled(boolean zoomGesturesEnabled) {
amap.getUiSettings().setZoomGesturesEnabled(zoomGesturesEnabled);
}
@Override
public void setScrollGesturesEnabled(boolean scrollGesturesEnabled) {
amap.getUiSettings().setScrollGesturesEnabled(scrollGesturesEnabled);
}
@Override
public void setRotateGesturesEnabled(boolean rotateGesturesEnabled) {
amap.getUiSettings().setRotateGesturesEnabled(rotateGesturesEnabled);
}
@Override
public void setTiltGesturesEnabled(boolean tiltGesturesEnabled) {
amap.getUiSettings().setTiltGesturesEnabled(tiltGesturesEnabled);
}
private CameraPosition getCameraPosition() {
if (null != amap) {
return amap.getCameraPosition();
}
return null;
}
@Override
public void onMyLocationChange(Location location) {
if (null != methodChannel && myLocationShowing) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("location", ConvertUtil.location2Map(location));
methodChannel.invokeMethod("location#changed", arguments);
LogUtil.i(CLASS_NAME, "onMyLocationChange===>" + arguments);
}
}
@Override
public void onCameraChange(CameraPosition cameraPosition) {
if (null != methodChannel) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("position", ConvertUtil.cameraPositionToMap(cameraPosition));
methodChannel.invokeMethod("camera#onMove", arguments);
LogUtil.i(CLASS_NAME, "onCameraChange===>" + arguments);
}
}
@Override
public void onCameraChangeFinish(CameraPosition cameraPosition) {
if (null != methodChannel) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("position", ConvertUtil.cameraPositionToMap(cameraPosition));
methodChannel.invokeMethod("camera#onMoveEnd", arguments);
LogUtil.i(CLASS_NAME, "onCameraChangeFinish===>" + arguments);
}
}
@Override
public void onMapClick(LatLng latLng) {
if (null != methodChannel) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("latLng", ConvertUtil.latLngToList(latLng));
methodChannel.invokeMethod("map#onTap", arguments);
LogUtil.i(CLASS_NAME, "onMapClick===>" + arguments);
}
}
@Override
public void onMapLongClick(LatLng latLng) {
if (null != methodChannel) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("latLng", ConvertUtil.latLngToList(latLng));
methodChannel.invokeMethod("map#onLongPress", arguments);
LogUtil.i(CLASS_NAME, "onMapLongClick===>" + arguments);
}
}
@Override
public void onPOIClick(Poi poi) {
if (null != methodChannel) {
final Map<String, Object> arguments = new HashMap<String, Object>(2);
arguments.put("poi", ConvertUtil.poiToMap(poi));
methodChannel.invokeMethod("map#onPoiTouched", arguments);
LogUtil.i(CLASS_NAME, "onPOIClick===>" + arguments);
}
}
private void moveCamera(CameraUpdate cameraUpdate, Object animatedObject, Object durationObject) {
boolean animated = false;
long duration = 250;
if (null != animatedObject) {
animated = (Boolean) animatedObject;
}
if (null != durationObject) {
duration = ((Number) durationObject).intValue();
}
if (null != amap) {
if (animated) {
amap.animateCamera(cameraUpdate, duration, null);
} else {
amap.moveCamera(cameraUpdate);
}
}
}
@Override
public void setInitialMarkers(Object initialMarkers) {
//不实现
}
@Override
public void setInitialPolylines(Object initialPolylines) {
//不实现
}
@Override
public void setInitialPolygons(Object polygonsObject) {
//不实现
}
}

View File

@ -0,0 +1,32 @@
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);
}
}

View File

@ -0,0 +1,111 @@
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();
}
}

View File

@ -0,0 +1,89 @@
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) {
}
}

View File

@ -0,0 +1,39 @@
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);
}

View File

@ -0,0 +1,98 @@
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);
}
}
}

View File

@ -0,0 +1,227 @@
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;
}
}
/**
* 执行主动方法更新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);
}
}

View File

@ -0,0 +1,62 @@
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) {
//不支持动态修改
}
}

View File

@ -0,0 +1,60 @@
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);
}
}

View File

@ -0,0 +1,32 @@
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);
}

View File

@ -0,0 +1,58 @@
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;
}
}
}

View File

@ -0,0 +1,129 @@
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();
}
}
}
}

View File

@ -0,0 +1,120 @@
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);
}
}

View File

@ -0,0 +1,103 @@
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;
}
}

View File

@ -0,0 +1,61 @@
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);
}

View File

@ -0,0 +1,108 @@
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;
}
}

View File

@ -0,0 +1,149 @@
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();
}
}
}
}

View File

@ -0,0 +1,50 @@
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_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_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_CLEAR_DISK};
/**
* markers
*/
public static final String METHOD_MARKER_UPDATE = "markers#update";
public static final String[] METHOD_ID_LIST_FOR_MARKER = {METHOD_MARKER_UPDATE};
/**
* 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};
}

View File

@ -0,0 +1,521 @@
package com.amap.flutter.map.utils;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Point;
import android.location.Location;
import android.text.TextUtils;
import com.amap.api.maps.AMap;
import com.amap.api.maps.CameraUpdate;
import com.amap.api.maps.CameraUpdateFactory;
import com.amap.api.maps.MapsInitializer;
import com.amap.api.maps.model.BitmapDescriptor;
import com.amap.api.maps.model.BitmapDescriptorFactory;
import com.amap.api.maps.model.CameraPosition;
import com.amap.api.maps.model.CustomMapStyleOptions;
import com.amap.api.maps.model.LatLng;
import com.amap.api.maps.model.LatLngBounds;
import com.amap.api.maps.model.MyLocationStyle;
import com.amap.api.maps.model.Poi;
import com.amap.flutter.map.core.AMapOptionsSink;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import androidx.annotation.NonNull;
import io.flutter.view.FlutterMain;
/**
* @author whm
* @date 2020/10/29 11:01 AM
* @mail hongming.whm@alibaba-inc.com
* @since
*/
public class ConvertUtil {
private static final String CLASS_NAME = "ConvertUtil";
public static float density;
private static String apiKey;
public static void setPrivacyStatement(Context context, Object object) {
if (null == object) {
return;
}
Map<?, ?> privacyStatementMap = toMap(object);
Object hasContainsObj = privacyStatementMap.get("hasContains");
Object hasShowObj = privacyStatementMap.get("hasShow");
Object hasAgreeObj = privacyStatementMap.get("hasAgree");
Class<MapsInitializer> clazz = MapsInitializer.class;
if (null != hasContainsObj
&& null != hasShowObj) {
boolean hasContains = toBoolean(hasContainsObj);
boolean hasShow = toBoolean(hasShowObj);
//使用反射的方法调用适配之前的版本
try {
Method method = clazz.getMethod("updatePrivacyShow", Context.class, boolean.class, boolean.class);
method.invoke(null, context, hasContains, hasShow);
} catch (Throwable e) {
// e.printStackTrace();
}
}
if (null != hasAgreeObj) {
boolean hasAgree = toBoolean(hasAgreeObj);
//使用反射的方法调用适配之前的版本
try{
Method method = clazz.getMethod("updatePrivacyAgree", Context.class, boolean.class);
method.invoke(null, context, hasAgree);
} catch (Throwable e) {
// e.printStackTrace();
}
}
}
public static void checkApiKey(Object object) {
if (null == object) {
return;
}
Map<?, ?> keyMap = toMap(object);
Object keyObject = keyMap.get("androidKey");
if (null != keyObject) {
final String aKey = toString(keyObject);
if (TextUtils.isEmpty(apiKey)
|| !aKey.equals(apiKey)) {
apiKey = aKey;
MapsInitializer.setApiKey(apiKey);
}
}
}
public static int toLocalMapType(int dartMapIndex) {
int[] localTypeArray = {AMap.MAP_TYPE_NORMAL, AMap.MAP_TYPE_SATELLITE, AMap.MAP_TYPE_NIGHT, AMap.MAP_TYPE_NAVI, AMap.MAP_TYPE_BUS};
if (dartMapIndex > localTypeArray.length) {
return localTypeArray[0];
}
return localTypeArray[dartMapIndex];
}
public static CameraUpdate toCameraUpdate(Object o) {
final List<?> data = toList(o);
switch (toString(data.get(0))) {
case "newCameraPosition":
return CameraUpdateFactory.newCameraPosition(toCameraPosition(data.get(1)));
case "newLatLng":
return CameraUpdateFactory.newLatLng(toLatLng(data.get(1)));
case "newLatLngBounds":
return CameraUpdateFactory.newLatLngBounds(
toLatLngBounds(data.get(1)), toPixels(data.get(2)));
case "newLatLngZoom":
return CameraUpdateFactory.newLatLngZoom(toLatLng(data.get(1)), toFloat(data.get(2)));
case "scrollBy":
return CameraUpdateFactory.scrollBy( //
toFloatPixels(data.get(1)), //
toFloatPixels(data.get(2)));
case "zoomBy":
if (data.size() == 2) {
return CameraUpdateFactory.zoomBy(toFloat(data.get(1)));
} else {
return CameraUpdateFactory.zoomBy(toFloat(data.get(1)), toPoint(data.get(2)));
}
case "zoomIn":
return CameraUpdateFactory.zoomIn();
case "zoomOut":
return CameraUpdateFactory.zoomOut();
case "zoomTo":
return CameraUpdateFactory.zoomTo(toFloat(data.get(1)));
default:
throw new IllegalArgumentException("Cannot interpret " + o + " as CameraUpdate");
}
}
private static Point toPoint(Object o) {
final List<?> data = toList(o);
return new Point(toPixels(data.get(0)), toPixels(data.get(1)));
}
public static float toFloatPixels(Object o) {
return toFloat(o) * density;
}
public static int toPixels(Object o) {
return (int) toFloatPixels(o);
}
/**
* 将一个对象转换成CameraPosition
*
* @param o
* @return
*/
public static CameraPosition toCameraPosition(Object o) {
final Map<?, ?> data = (Map<?, ?>) o;
final CameraPosition.Builder builder = CameraPosition.builder();
builder.bearing(toFloat(data.get("bearing")));
builder.target(toLatLng(data.get("target")));
builder.tilt(toFloat(data.get("tilt")));
builder.zoom(toFloat(data.get("zoom")));
return builder.build();
}
public static Object cameraPositionToMap(CameraPosition position) {
if (position == null) {
return null;
}
final Map<String, Object> data = new HashMap<>();
data.put("bearing", position.bearing);
data.put("target", latLngToList(position.target));
data.put("tilt", position.tilt);
data.put("zoom", position.zoom);
return data;
}
/**
* 转换AMapOptions
*
* @param o
* @param sink
*/
public static void interpretAMapOptions(Object o, @NonNull AMapOptionsSink sink) {
try {
final Map<?, ?> data = (Map<?, ?>) o;
final Object mapType = data.get("mapType");
if (mapType != null) {
sink.setMapType(toLocalMapType(toInt(mapType)));
}
final Object buildingsEnabled = data.get("buildingsEnabled");
if (null != buildingsEnabled) {
sink.setBuildingsEnabled(toBoolean(buildingsEnabled));
}
final Object customMapStyleOptions = data.get("customStyleOptions");
if (null != customMapStyleOptions) {
CustomMapStyleOptions customMapStyleOptions1 = toCustomMapStyleOptions(customMapStyleOptions);
sink.setCustomMapStyleOptions(customMapStyleOptions1);
}
final Object myLocationStyleData = data.get("myLocationStyle");
if (null != myLocationStyleData) {
sink.setMyLocationStyle(ConvertUtil.toMyLocationStyle(myLocationStyleData, density));
}
final Object screenAnchor = data.get("screenAnchor");
if (null != screenAnchor) {
final List<?> anchorData = toList(screenAnchor);
sink.setScreenAnchor(toFloat(anchorData.get(0)), toFloat(anchorData.get(1)));
}
final Object compassEnabled = data.get("compassEnabled");
if (null != compassEnabled) {
sink.setCompassEnabled(toBoolean(compassEnabled));
}
final Object labelsEnabled = data.get("labelsEnabled");
if (null != labelsEnabled) {
sink.setLabelsEnabled(toBoolean(labelsEnabled));
}
final Object limitBounds = data.get("limitBounds");
if (null != limitBounds) {
final List<?> targetData = toList(limitBounds);
sink.setLatLngBounds(toLatLngBounds(targetData));
}
final Object minMaxZoomPreference = data.get("minMaxZoomPreference");
if (null != minMaxZoomPreference) {
final List<?> targetData = toList(minMaxZoomPreference);
sink.setMinZoomLevel(toFloatWrapperWithDefault(targetData.get(0), 3));
sink.setMaxZoomLevel(toFloatWrapperWithDefault(targetData.get(1), 20));
}
final Object scaleEnabled = data.get("scaleEnabled");
if (null != scaleEnabled) {
sink.setScaleEnabled(toBoolean(scaleEnabled));
}
final Object touchPoiEnabled = data.get("touchPoiEnabled");
if (null != touchPoiEnabled) {
sink.setTouchPoiEnabled(toBoolean(touchPoiEnabled));
}
final Object trafficEnabled = data.get("trafficEnabled");
if (null != trafficEnabled) {
sink.setTrafficEnabled(toBoolean(trafficEnabled));
}
final Object rotateGesturesEnabled = data.get("rotateGesturesEnabled");
if (null != rotateGesturesEnabled) {
sink.setRotateGesturesEnabled(toBoolean(rotateGesturesEnabled));
}
final Object scrollGesturesEnabled = data.get("scrollGesturesEnabled");
if (null != scrollGesturesEnabled) {
sink.setScrollGesturesEnabled(toBoolean(scrollGesturesEnabled));
}
final Object tiltGesturesEnabled = data.get("tiltGesturesEnabled");
if (null != tiltGesturesEnabled) {
sink.setTiltGesturesEnabled(toBoolean(tiltGesturesEnabled));
}
final Object zoomGesturesEnabled = data.get("zoomGesturesEnabled");
if (null != zoomGesturesEnabled) {
sink.setZoomGesturesEnabled(toBoolean(zoomGesturesEnabled));
}
} catch (Throwable e) {
LogUtil.e(CLASS_NAME, "interpretAMapOptions", e);
}
}
private static CustomMapStyleOptions toCustomMapStyleOptions(Object o) {
final Map<?, ?> map = toMap(o);
final CustomMapStyleOptions customMapStyleOptions = new CustomMapStyleOptions();
final Object enableData = map.get("enabled");
if (null != enableData) {
customMapStyleOptions.setEnable(toBoolean(enableData));
}
final Object styleData = map.get("styleData");
if (null != styleData) {
customMapStyleOptions.setStyleData((byte[]) styleData);
}
final Object styleExtraData = map.get("styleExtraData");
if (null != styleExtraData) {
customMapStyleOptions.setStyleExtraData((byte[]) styleExtraData);
}
return customMapStyleOptions;
}
private static final int[] LocationTypeMap = new int[]{MyLocationStyle.LOCATION_TYPE_SHOW, MyLocationStyle.LOCATION_TYPE_FOLLOW, MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE};
private static MyLocationStyle toMyLocationStyle(Object o, float density) {
final Map<?, ?> map = toMap(o);
final MyLocationStyle myLocationStyle = new MyLocationStyle();
final Object enableData = map.get("enabled");
if (null != enableData) {
myLocationStyle.showMyLocation(toBoolean(enableData));
}
//两端差异比较大Android端设置成跟随但是不移动到中心点模式与iOS端兼容
myLocationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_FOLLOW_NO_CENTER);
// final Object trackingMode = map.get("trackingMode");
// if (null != trackingMode) {
// int trackingModeIndex = toInt(trackingMode);
// if (trackingModeIndex < LocationTypeMap.length) {
// myLocationStyle.myLocationType(LocationTypeMap[trackingModeIndex]);
// }
// }
final Object circleFillColorData = map.get("circleFillColor");
if (null != circleFillColorData) {
myLocationStyle.radiusFillColor(toInt(circleFillColorData));
}
final Object circleStrokeColorData = map.get("circleStrokeColor");
if (null != circleStrokeColorData) {
myLocationStyle.strokeColor(toInt(circleStrokeColorData));
}
final Object circleStrokeWidthData = map.get("circleStrokeWidth");
if (null != circleStrokeWidthData) {
myLocationStyle.strokeWidth(toPixels(circleStrokeWidthData));
}
final Object iconDta = map.get("icon");
if (null != iconDta) {
myLocationStyle.myLocationIcon(toBitmapDescriptor(iconDta));
}
return myLocationStyle;
}
public static Object location2Map(Location location) {
if (null == location) {
return null;
}
if (location.getAltitude() > 90 ||
location.getAltitude() < -90 ||
location.getLongitude() > 180 ||
location.getLongitude() < -180) {
return null;
}
final Map<String, Object> object = new HashMap<String, Object>();
object.put("provider", location.getProvider());
object.put("latLng", Arrays.asList(location.getLatitude(), location.getLongitude()));
object.put("accuracy", location.getAccuracy());
object.put("altitude", location.getAltitude());
object.put("bearing", location.getBearing());
object.put("speed", location.getSpeed());
object.put("time", location.getTime());
return object;
}
public static BitmapDescriptor toBitmapDescriptor(Object o) {
final List<?> data = toList(o);
switch (toString(data.get(0))) {
case "defaultMarker":
if (data.size() == 1) {
return BitmapDescriptorFactory.defaultMarker();
} else {
return BitmapDescriptorFactory.defaultMarker(toFloat(data.get(1)));
}
case "fromAsset":
if (data.size() == 2) {
return BitmapDescriptorFactory.fromAsset(
FlutterMain.getLookupKeyForAsset(toString(data.get(1))));
} else {
return BitmapDescriptorFactory.fromAsset(
FlutterMain.getLookupKeyForAsset(toString(data.get(1)), toString(data.get(2))));
}
case "fromAssetImage":
if (data.size() == 3) {
return BitmapDescriptorFactory.fromAsset(
FlutterMain.getLookupKeyForAsset(toString(data.get(1))));
} else {
throw new IllegalArgumentException(
"'fromAssetImage' Expected exactly 3 arguments, got: " + data.size());
}
case "fromBytes":
return getBitmapFromBytes(data);
default:
throw new IllegalArgumentException("Cannot interpret " + o + " as BitmapDescriptor");
}
}
public static List<BitmapDescriptor> toBitmapDescriptorList(Object o) {
List<?> rawList = ConvertUtil.toList(o);
List<BitmapDescriptor> bitmapDescriptorList = new ArrayList<BitmapDescriptor>();
for (Object obj : rawList) {
bitmapDescriptorList.add(ConvertUtil.toBitmapDescriptor(obj));
}
return bitmapDescriptorList;
}
private static BitmapDescriptor getBitmapFromBytes(List<?> data) {
if (data.size() == 2) {
try {
Bitmap bitmap = toBitmap(data.get(1));
return BitmapDescriptorFactory.fromBitmap(bitmap);
} catch (Exception e) {
throw new IllegalArgumentException("Unable to interpret bytes as a valid image.", e);
}
} else {
throw new IllegalArgumentException(
"fromBytes should have exactly one argument, the bytes. Got: " + data.size());
}
}
private static Bitmap toBitmap(Object o) {
byte[] bmpData = (byte[]) o;
Bitmap bitmap = BitmapFactory.decodeByteArray(bmpData, 0, bmpData.length);
if (bitmap == null) {
throw new IllegalArgumentException("Unable to decode bytes as a valid bitmap.");
} else {
return bitmap;
}
}
public static Object poiToMap(Poi poi) {
if (null == poi) {
return null;
}
final Map<String, Object> data = new HashMap<>();
data.put("id", poi.getPoiId());
data.put("name", poi.getName());
data.put("latLng", latLngToList(poi.getCoordinate()));
return data;
}
public static Object latLngToList(LatLng latLng) {
if (null == latLng) {
return null;
}
return Arrays.asList(latLng.latitude, latLng.longitude);
}
public static LatLng toLatLng(Object o) {
final List<?> data = (List<?>) o;
return new LatLng((Double) data.get(0), (Double) data.get(1));
}
public static List<LatLng> toPoints(Object o) {
final List<?> data = toList(o);
final List<LatLng> points = new ArrayList<>(data.size());
for (Object ob : data) {
final List<?> point = toList(ob);
points.add(new LatLng(toFloat(point.get(0)), toFloat(point.get(1))));
}
return points;
}
public static LatLngBounds toLatLngBounds(Object o) {
if (o == null) {
return null;
}
final List<?> data = toList(o);
return new LatLngBounds(toLatLng(data.get(0)), toLatLng(data.get(1)));
}
private static Float toFloatWrapper(Object o) {
return (o == null) ? null : toFloat(o);
}
public static Float toFloatWrapperWithDefault(Object o, float defaultValue) {
return (o == null) ? defaultValue : toFloat(o);
}
public static boolean toBoolean(Object o) {
return (Boolean) o;
}
public static int toInt(Object o) {
return ((Number) o).intValue();
}
public static double toDouble(Object o) {
return ((Number) o).doubleValue();
}
public static float toFloat(Object o) {
return ((Number) o).floatValue();
}
public static List<?> toList(Object o) {
return (List<?>) o;
}
public static Map<?, ?> toMap(Object o) {
return (Map<?, ?>) o;
}
public static String toString(Object o) {
return (String) o;
}
public static Object getKeyValueFromMapObject(Object object, String keyStr) {
if (null == object) {
return null;
}
try {
Map<?, ?> mapData = toMap(object);
return mapData.get(keyStr);
} catch (Throwable e) {
e.printStackTrace();
}
return null;
}
}

View File

@ -0,0 +1,39 @@
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);
}
}
}