Browse Source

update: 修改map view

hwh97 5 years ago
parent
commit
53c51ece7e

+ 2 - 38
android/src/main/kotlin/com/i2edu/amap_location/AMapHandler.kt

@@ -1,6 +1,5 @@
 package com.i2edu.amap_location
 
-import android.content.Context
 import android.util.Log
 import com.amap.api.location.AMapLocation
 import com.amap.api.location.AMapLocationClient
@@ -8,29 +7,16 @@ import com.amap.api.location.AMapLocationClientOption
 import com.amap.api.location.AMapLocationListener
 import io.flutter.plugin.common.MethodCall
 import io.flutter.plugin.common.MethodChannel
-import io.flutter.plugin.common.StandardMessageCodec
-import io.flutter.plugin.platform.PlatformView
-import io.flutter.plugin.platform.PlatformViewFactory
 
 class AMapHandler(private val flutterState: FlutterState) :
         MethodChannel.MethodCallHandler, AMapLocationListener {
     private var client: AMapLocationClient? = null
-    private var mapView: AMapView? = null
 
     override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
         when (call.method) {
             "getPlatformVersion" -> {
                 result.success("Android ${android.os.Build.VERSION.RELEASE}")
             }
-            "registerView" -> {
-                mapView = AMapView(flutterState.context, flutterState.methodChannel)
-                flutterState.platformViewRegistry.registerViewFactory("com.i2edu.mapView", object : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
-                    override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
-                        return mapView!!
-                    }
-                })
-                result.success(true)
-            }
             "startLocation" -> {
                 if (client == null) {
                     client = AMapLocationClient(flutterState.context)
@@ -49,28 +35,6 @@ class AMapHandler(private val flutterState: FlutterState) :
                 stopLocation()
                 result.success("success")
             }
-            // map view
-            "onCreate" -> {
-                mapView?.onCreate()
-                result.success(true)
-            }
-            "onPause" -> {
-                mapView?.onPause()
-                result.success(true)
-            }
-            "onResume" -> {
-                mapView?.onResume()
-                result.success(true)
-            }
-            "setMarkers" -> {
-                val data = call.argument<List<Map<String, Any>>>("markers")!!
-                mapView?.setMarkers(data)
-                result.success(true)
-            }
-            "onDestroy" -> {
-                mapView?.dispose()
-                result.success(true)
-            }
             else -> {
                 result.notImplemented()
             }
@@ -93,8 +57,8 @@ class AMapHandler(private val flutterState: FlutterState) :
 
     // 停止定位
     private fun stopLocation() {
-        client?.stopLocation();
-        client?.onDestroy();
+        client?.stopLocation()
+        client?.onDestroy()
         client = null
     }
 

+ 76 - 51
android/src/main/kotlin/com/i2edu/amap_location/AMapView.kt

@@ -13,70 +13,70 @@ import com.amap.api.maps.AMap
 import com.amap.api.maps.CameraUpdateFactory
 import com.amap.api.maps.MapView
 import com.amap.api.maps.model.*
+import io.flutter.embedding.engine.plugins.activity.ActivityAware
+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
 import java.util.*
 
 
-class AMapView(private val context: Context, private val channel: MethodChannel) : PlatformView,
+class AMapView(private val context: Context, messenger: BinaryMessenger, id: Int, params: Any?) : PlatformView, MethodChannel.MethodCallHandler,
         AMap.OnMyLocationChangeListener, AMap.InfoWindowAdapter {
     private val TAG = "AMapView"
-    var frameLayout: FrameLayout? = null
-    var mapView: MapView? = null
-    var aMap: AMap? = null
-    var infoWindow: View? = null
-    var mMarkers: List<Map<String, Any>>? = null
+    private var frameLayout: FrameLayout? = null
+    private var mapView: MapView? = null
+    private var aMap: AMap? = null
+    private var infoWindow: View? = null
+    private var mMarkers: List<Map<String, Any>>? = null
     private var firstMove: Boolean = false
-
-    private fun setUpView(context: Context) {
-        if (frameLayout == null) {
-            frameLayout = FrameLayout(context)
-            frameLayout?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
-            mapView = MapView(context)
-            mapView?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
-            frameLayout?.addView(mapView)
-        }
-    }
-
-    fun onCreate() {
-        // TODO SaveInstance restore
-        mapView?.onCreate(null)
-        if (aMap == null) {
-            aMap = mapView?.map
-        }
-        val locationStyle = MyLocationStyle()
-        locationStyle.showMyLocation(true)
-        locationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.dog))
-        locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
-        aMap?.myLocationStyle = locationStyle
-        aMap?.isMyLocationEnabled = true
-        aMap?.uiSettings?.isMyLocationButtonEnabled = true
-        aMap?.setOnMyLocationChangeListener(this)
-        aMap?.setInfoWindowAdapter(this)
-    }
-
-    fun onPause() {
-        mapView?.onPause()
-    }
-
-    fun onResume() {
-        mapView?.onResume()
-    }
-
-    fun setMarkers(markers: List<Map<String, Any>>) {
-        this.mMarkers = markers
-
-        aMap?.addMarkers(mMarkers?.map {
-            MarkerOptions().position(LatLng(it["lat"].toString().toDouble(), it["lon"].toString().toDouble()))
-                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.i2)).title(it["title"].toString())
-        }?.toList() as ArrayList<MarkerOptions>, false)
+    private var methodChannel: MethodChannel? = null
+
+    init {
+        frameLayout = FrameLayout(context)
+        frameLayout?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+        mapView = MapView(context)
+        mapView?.layoutParams = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
+        frameLayout?.addView(mapView)
+        methodChannel = MethodChannel(messenger, "com.i2edu.mapView/map_view_$id")
+        methodChannel?.setMethodCallHandler(this)
     }
 
     override fun getView(): View {
-        setUpView(context)
         return frameLayout!!
     }
 
+    override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) {
+        when (call.method) {
+            // map view
+            "onCreate" -> {
+                createMapView()
+                result.success(true)
+            }
+            "onPause" -> {
+                mapView?.onPause()
+                result.success(true)
+            }
+            "onResume" -> {
+                mapView?.onResume()
+                result.success(true)
+            }
+            "onDestroy" -> {
+                dispose()
+                result.success(true)
+            }
+            "setMarkers" -> {
+                val data = call.argument<List<Map<String, Any>>>("markers")!!
+                setMarkers(data)
+                result.success(true)
+            }
+            else -> {
+                result.notImplemented()
+            }
+        }
+    }
+
     override fun dispose() {
         firstMove = false
         mMarkers = null
@@ -116,6 +116,31 @@ class AMapView(private val context: Context, private val channel: MethodChannel)
         return infoWindow!!
     }
 
+    private fun createMapView() {
+        mapView?.onCreate(null)
+        if (aMap == null) {
+            aMap = mapView?.map
+        }
+        val locationStyle = MyLocationStyle()
+        locationStyle.showMyLocation(true)
+        locationStyle.myLocationIcon(BitmapDescriptorFactory.fromResource(R.drawable.dog))
+        locationStyle.myLocationType(MyLocationStyle.LOCATION_TYPE_LOCATION_ROTATE_NO_CENTER)
+        aMap?.myLocationStyle = locationStyle
+        aMap?.isMyLocationEnabled = true
+        aMap?.uiSettings?.isMyLocationButtonEnabled = true
+        aMap?.setOnMyLocationChangeListener(this)
+        aMap?.setInfoWindowAdapter(this)
+    }
+
+    private fun setMarkers(markers: List<Map<String, Any>>) {
+        this.mMarkers = markers
+
+        aMap?.addMarkers(mMarkers?.map {
+            MarkerOptions().position(LatLng(it["lat"].toString().toDouble(), it["lon"].toString().toDouble()))
+                    .icon(BitmapDescriptorFactory.fromResource(R.drawable.i2)).title(it["title"].toString())
+        }?.toList() as ArrayList<MarkerOptions>, false)
+    }
+
     private fun render(marker: Marker?, view: View?) {
         val tvTitle = view?.findViewById<TextView>(R.id.tv_title)
         val tvContent = view?.findViewById<TextView>(R.id.tv_content)
@@ -135,7 +160,7 @@ class AMapView(private val context: Context, private val channel: MethodChannel)
             tvTel?.text = "电话:${map["tel"].toString()}"
             tvGuide?.setOnClickListener {
                 // return data to flutter
-                channel.invokeMethod("guide", map)
+                methodChannel?.invokeMethod("guide", map)
             }
         }
     }

+ 9 - 2
android/src/main/kotlin/com/i2edu/amap_location/FlutterState.kt

@@ -3,16 +3,23 @@ package com.i2edu.amap_location
 import android.content.Context
 import io.flutter.plugin.common.MethodChannel
 import io.flutter.plugin.common.BinaryMessenger
+import io.flutter.plugin.common.StandardMessageCodec
+import io.flutter.plugin.platform.PlatformView
+import io.flutter.plugin.platform.PlatformViewFactory
 import io.flutter.plugin.platform.PlatformViewRegistry
 
 class FlutterState(
         val context: Context,
-        binaryMessenger: BinaryMessenger,
+        val binaryMessenger: BinaryMessenger,
         val platformViewRegistry: PlatformViewRegistry) {
-    
     val methodChannel: MethodChannel = MethodChannel(binaryMessenger, "amap_location")
 
     fun startListening(methodCallHandler: AMapHandler) {
+        platformViewRegistry.registerViewFactory("com.i2edu.mapView", object : PlatformViewFactory(StandardMessageCodec.INSTANCE) {
+            override fun create(context: Context, viewId: Int, args: Any?): PlatformView {
+                return AMapView(context, binaryMessenger, viewId, args)
+            }
+        })
         methodChannel.setMethodCallHandler(methodCallHandler)
     }
 

+ 0 - 1
example/lib/main.dart

@@ -8,7 +8,6 @@ import 'package:flutter/services.dart';
 
 void main() {
   WidgetsFlutterBinding.ensureInitialized();
-  AmapLocation.registerView();
   runApp(MyApp());
 }
 

+ 13 - 8
example/lib/map_view_page.dart

@@ -13,6 +13,8 @@ class MapViewPage extends StatefulWidget {
 }
 
 class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
+  final AmapViewController controller = AmapViewController();
+
   @override
   Widget build(BuildContext context) {
     return Scaffold(
@@ -20,7 +22,10 @@ class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
       body: SizedBox(
         height: double.maxFinite,
         width: double.maxFinite,
-        child: AmapLocation.instance.buildMapView(_onPlatformCreate),
+        child: AmapView(
+          controller: controller,
+          onViewCreated: _onPlatformCreate,
+        ),
       ),
     );
   }
@@ -34,7 +39,7 @@ class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
   @override
   void dispose() {
     WidgetsBinding.instance.removeObserver(this);
-    AmapLocation.instance.disposedMapView();
+    controller.dispose();
     super.dispose();
   }
 
@@ -42,9 +47,9 @@ class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
   void didChangeAppLifecycleState(AppLifecycleState state) {
     super.didChangeAppLifecycleState(state);
     if (state == AppLifecycleState.paused) {
-      AmapLocation.instance.onPauseMapView();
+      controller.onPauseMapView();
     } else if (state == AppLifecycleState.resumed) {
-      AmapLocation.instance.onResumeMapView();
+      controller.onResumeMapView();
     }
   }
 
@@ -52,13 +57,13 @@ class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
     // kingWay 的环境
     var httpClient = new HttpClient();
     HttpClientRequest request = await httpClient
-        .getUrl(Uri.http("172.16.11.77:8086", "/api/v1/school_map/all_addr"));
+        .getUrl(Uri.http("47.103.219.158:31103", "/api/v1/school_map/all_addr"));
     var response = await request.close();
     var responseBody = await response.transform(Utf8Decoder()).join();
     List<Map> data = jsonDecode(responseBody)['data'].cast<Map>();
     print(data.toString());
 
-    AmapLocation.instance.setMapMarkers(data.map((f) {
+    controller.setMapMarkers(data.map((f) {
       var coordinate = f['coordinate'].toString().split(",");
       return AmapMarker(
           double.parse(coordinate[1]),
@@ -69,9 +74,9 @@ class _MapViewPageState extends State<MapViewPage> with WidgetsBindingObserver {
 
   void _onPlatformCreate() {
     print("on map view create");
-    AmapLocation.instance.onCreateMapView();
+    controller.onCreateMapView();
     initCityData();
-    AmapLocation.instance.guideStream.listen((m) {
+    controller.guideStream.listen((m) {
       showModalBottomSheet(
           context: context,
           builder: (context) {

+ 3 - 1
lib/amap_export.dart

@@ -3,4 +3,6 @@ library amap_location;
 export 'amap_location.dart';
 export 'location_option.dart';
 export 'location_result_entity.dart';
-export 'amap_marker.dart';
+export 'amap_marker.dart';
+export 'amap_view.dart';
+export 'amap_view_controller.dart';

+ 8 - 53
lib/amap_location.dart

@@ -14,20 +14,19 @@ import 'location_result_entity.dart';
 class AmapLocation {
   static const MethodChannel _channel = const MethodChannel('amap_location');
   static final AmapLocation _instance = AmapLocation();
-  static const String viewType = "com.i2edu.mapView";
 
   static AmapLocation get instance => _instance;
 
   StreamController _locationStreamController;
-  StreamController _guideStreamController;
 
-  Stream<LocationResultEntity> get locationStream => _locationStreamController.stream;
-  Stream<Map> get guideStream => _guideStreamController.stream;
+  Stream<LocationResultEntity> get locationStream =>
+      _locationStreamController.stream;
+
 
   AmapLocation() {
     _channel.setMethodCallHandler(platformCallHandler);
-    _locationStreamController = StreamController<LocationResultEntity>.broadcast();
-    _guideStreamController = StreamController<Map>.broadcast();
+    _locationStreamController =
+        StreamController<LocationResultEntity>.broadcast();
   }
 
   static Future<String> get platformVersion async {
@@ -35,43 +34,10 @@ class AmapLocation {
     return version;
   }
 
-  static Future<void> registerView() async {
-    return await _channel.invokeMethod('registerView');
-  }
-
-  Widget buildMapView(VoidCallback onPlatformViewCreated) =>
-      Platform.isAndroid
-          ? AndroidView(
-        viewType: viewType,
-        creationParams: {},
-        creationParamsCodec: const StandardMessageCodec(),
-        onPlatformViewCreated: (id) => onPlatformViewCreated(),
-      ) : UiKitView(
-        viewType: viewType,
-        creationParams: {},
-        creationParamsCodec: const StandardMessageCodec(),
-        onPlatformViewCreated: (id) => onPlatformViewCreated(),
-      );
-
-  Future<void> setMapMarkers(List<AmapMarker> markers) async {
-    return await _channel.invokeMethod("setMarkers", {"markers":  markers.map((f) => f.toMap()).toList()});
-  }
-
-  Future<void> onCreateMapView() async {
-    return await _channel.invokeMethod('onCreate');
-  }
-
-  Future<void> onPauseMapView() async {
-    return await _channel.invokeMethod('onPause');
-  }
-
-  Future<void> onResumeMapView() async {
-    return await _channel.invokeMethod('onResume');
-  }
-
   Future<void> startLocation({LocationOption options}) async {
     if (_locationStreamController == null) {
-      _locationStreamController = StreamController<LocationResultEntity>.broadcast();
+      _locationStreamController =
+          StreamController<LocationResultEntity>.broadcast();
     }
     return await _channel.invokeMethod(
         'startLocation', options?.toMap() ?? LocationOption().toMap());
@@ -81,26 +47,15 @@ class AmapLocation {
     if (!_locationStreamController.isClosed) {
       await _locationStreamController.close();
     }
-    _locationStreamController = null;
     return await _channel.invokeMethod("closeLocation");
   }
 
-  Future<void> disposedMapView() async {
-    if (!_guideStreamController.isClosed) {
-      await _guideStreamController.close();
-    }
-    _guideStreamController = null;
-    return;
-  }
-
   Future<void> platformCallHandler(MethodCall call) async {
     try {
       if (call.method == "location") {
         LocationResultEntity entity =
-        LocationResultEntity().fromJson(jsonDecode(call.arguments));
+            LocationResultEntity().fromJson(jsonDecode(call.arguments));
         _locationStreamController.add(entity);
-      } else if (call.method == "guide") {
-        _guideStreamController.add(call.arguments);
       }
     } catch (ex) {
       print('Unexpected error: $ex');

+ 41 - 0
lib/amap_view.dart

@@ -0,0 +1,41 @@
+import 'dart:io';
+
+import 'package:amap_location/amap_view_controller.dart';
+import 'package:flutter/material.dart';
+import 'package:flutter/services.dart';
+
+class AmapView extends StatefulWidget {
+  final AmapViewController controller;
+  final VoidCallback onViewCreated;
+
+  const AmapView({Key key, @required this.controller, this.onViewCreated}) : super(key: key);
+
+  @override
+  _AmapViewState createState() => _AmapViewState();
+}
+
+class _AmapViewState extends State<AmapView> {
+  static const String viewType = "com.i2edu.mapView";
+
+  @override
+  Widget build(BuildContext context) {
+    return Platform.isAndroid
+        ? AndroidView(
+            viewType: viewType,
+            creationParams: {},
+            creationParamsCodec: const StandardMessageCodec(),
+            onPlatformViewCreated: onPlatformViewCreated,
+          )
+        : UiKitView(
+            viewType: viewType,
+            creationParams: {},
+            creationParamsCodec: const StandardMessageCodec(),
+            onPlatformViewCreated: onPlatformViewCreated,
+          );
+  }
+
+  void onPlatformViewCreated(int id) {
+    widget.controller.init(id);
+    widget.onViewCreated();
+  }
+}

+ 57 - 0
lib/amap_view_controller.dart

@@ -0,0 +1,57 @@
+
+import 'dart:async';
+
+import 'package:flutter/services.dart';
+
+import 'amap_marker.dart';
+
+class AmapViewController {
+  MethodChannel _methodChannel;
+
+  StreamController _guideStreamController;
+  Stream<Map> get guideStream => _guideStreamController.stream;
+
+  void init(int id) {
+    _methodChannel = MethodChannel("com.i2edu.mapView/map_view_$id");
+    _methodChannel.setMethodCallHandler(platformCallHandler);
+    _guideStreamController = StreamController<Map>.broadcast();
+  }
+
+  Future<void> platformCallHandler(MethodCall call) async {
+    try {
+      if (call.method == "guide") {
+        _guideStreamController.add(call.arguments);
+      }
+    } catch (ex) {
+      print('Unexpected error: $ex');
+    }
+    return null;
+  }
+
+  Future<void> setMapMarkers(List<AmapMarker> markers) async {
+    assert(_methodChannel != null);
+    return await _methodChannel.invokeMethod(
+        "setMarkers", {"markers": markers.map((f) => f.toMap()).toList()});
+  }
+
+  Future<void> onCreateMapView() async {
+    assert(_methodChannel != null);
+    return await _methodChannel.invokeMethod('onCreate');
+  }
+
+  Future<void> onPauseMapView() async {
+    assert(_methodChannel != null);
+    return await _methodChannel.invokeMethod('onPause');
+  }
+
+  Future<void> onResumeMapView() async {
+    assert(_methodChannel != null);
+    return await _methodChannel.invokeMethod('onResume');
+  }
+
+  void dispose() {
+    if (!_guideStreamController.isClosed) {
+      _guideStreamController.close();
+    }
+  }
+}