Browse Source

[new]完善轨迹停留、异常、运动轨迹线路功能

zk 6 tháng trước cách đây
mục cha
commit
240cbecb28
24 tập tin đã thay đổi với 359 bổ sung96 xóa
  1. 5 1
      lib/data/consts/constants.dart
  2. 24 2
      lib/module/track/track_controller.dart
  3. 71 58
      lib/module/track/track_day_detail/track_daily_item.dart
  4. 22 4
      lib/module/track/track_day_detail/track_day_detail_controller.dart
  5. 6 4
      lib/module/track/track_day_detail/track_day_detail_view.dart
  6. 13 0
      lib/module/track/track_util.dart
  7. 2 1
      plugins/map/lib/flutter_map.dart
  8. 2 0
      plugins/map/lib/src/consts/map_constants.dart
  9. 3 2
      plugins/map/lib/src/consts/marker_type.dart
  10. 9 0
      plugins/map/lib/src/consts/polyline_type.dart
  11. 41 4
      plugins/map/lib/src/core/map_controller.dart
  12. 3 0
      plugins/map/lib/src/interface/map_marker_interface.dart
  13. 6 2
      plugins/map/lib/src/interface/map_polyline_interface.dart
  14. 3 2
      plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/bean/MakerInfo.java
  15. 5 5
      plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/contants/Constants.java
  16. 35 5
      plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/marker/MarkersController.java
  17. 44 5
      plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/polyline/PolylineController.java
  18. 15 0
      plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/polyline/PolylineType.java
  19. BIN
      plugins/map_amap_android/android/src/main/res/drawable-xxhdpi/bg_map_error_line.webp
  20. BIN
      plugins/map_amap_android/android/src/main/res/drawable-xxhdpi/bg_map_selected_line.webp
  21. 6 0
      plugins/map_amap_android/android/src/main/res/drawable/bg_track_error_point.xml
  22. 9 0
      plugins/map_amap_android/android/src/main/res/drawable/icon_marker_error.xml
  23. 35 0
      plugins/map_amap_android/android/src/main/res/layout/item_track_error_marker.xml
  24. 0 1
      plugins/map_amap_android/android/src/main/res/layout/item_track_selected_marker.xml

+ 5 - 1
lib/data/consts/constants.dart

@@ -39,7 +39,11 @@ class Constants {
   static const String mineLocationId = '';
   static const String traceStartId = '-100';
   static const String traceEndId = '-200';
-  static const String traceSelectId = '-300';
+  static const String tracePopupId = '-300';
+  static const String traceErrorId = '-400';
+
+  static const String traceNormalLineId = '-1000';
+  static const String traceSelectLineId = '-2000';
 
   static const double blurredX = 4.2;
   static const double blurredY = 4.2;

+ 24 - 2
lib/module/track/track_controller.dart

@@ -6,6 +6,7 @@ import 'package:get/get_core/src/get_main.dart';
 import 'package:injectable/injectable.dart';
 import 'package:location/base/base_controller.dart';
 import 'package:location/data/bean/track_days.dart';
+import 'package:location/data/consts/constants.dart';
 import 'package:location/data/repositories/account_repository.dart';
 import 'package:location/data/repositories/friends_repository.dart';
 import 'package:location/data/repositories/track_repository.dart';
@@ -36,7 +37,7 @@ class TrackController extends BaseController
       MapPadding(left: 50.w, top: 100.w, right: 50.w, bottom: Get.height / 2);
 
   final selectPadding =
-  MapPadding(left: 80.w, top: 150.w, right: 80.w, bottom: Get.height / 2);
+      MapPadding(left: 80.w, top: 150.w, right: 80.w, bottom: Get.height / 2);
 
   final TrackRepository trackRepository;
   final FriendsRepository friendsRepository;
@@ -102,7 +103,8 @@ class TrackController extends BaseController
     mapController.clear();
     //画折线
     if (points.length > 1) {
-      mapController.addPolyline(points, mapPadding: mapPadding);
+      mapController.addPolyline(Constants.traceNormalLineId, points,
+          mapPadding: mapPadding);
     }
     //画标记点
     if (markers.isNotEmpty) {
@@ -111,6 +113,7 @@ class TrackController extends BaseController
   }
 
   void showSelectMarker(List<LatLng> points, Marker selectMarker) {
+    _clearSelectMapMarker();
     mapController.updateOrAddMarker(selectMarker);
     mapController.moveToSuitableLocation(points, mapPadding: selectPadding);
   }
@@ -119,6 +122,25 @@ class TrackController extends BaseController
     Get.back();
   }
 
+  void showMovingTrack(List<LatLng> movingPoints) {
+    _clearSelectMapMarker();
+    mapController.addPolyline(Constants.traceSelectLineId, movingPoints,
+        lineType: PolylineType.selected, mapPadding: mapPadding);
+  }
+
+  void showTrackError(List<LatLng> errorPoints, Marker errorMarker) {
+    _clearSelectMapMarker();
+    mapController.updateOrAddMarker(errorMarker);
+    mapController.addPolyline(Constants.traceSelectLineId, errorPoints,
+        lineType: PolylineType.error, mapPadding: mapPadding);
+  }
+
+  void _clearSelectMapMarker() {
+    mapController.removePolyline(Constants.traceSelectLineId);
+    mapController.removeMarker(Constants.tracePopupId);
+    mapController.removeMarker(Constants.traceErrorId);
+  }
+
   @override
   void onClose() {
     super.onClose();

+ 71 - 58
lib/module/track/track_day_detail/track_daily_item.dart

@@ -26,11 +26,11 @@ Widget buildTrackDailyItem(TrackDailyBean bean, bool isEnd,
       children: [
         Builder(builder: (context) {
           if (bean.status == TrackStatus.moving) {
-            return _buildMovingTrackDailyItem(bean);
+            return _buildMovingTrackDailyItem(bean, onItemClick: onItemClick);
           } else if (bean.status == TrackStatus.stay) {
             return buildStayTrackDailyItem(bean, onItemClick: onItemClick);
           } else if (bean.status == TrackStatus.error) {
-            return buildErrorTrackDailyItem(bean);
+            return buildErrorTrackDailyItem(bean, onItemClick: onItemClick);
           } else {
             return SizedBox(height: 50.w, child: Text('未知轨迹,请更新最新应用版本'));
           }
@@ -41,7 +41,8 @@ Widget buildTrackDailyItem(TrackDailyBean bean, bool isEnd,
   );
 }
 
-Widget _buildMovingTrackDailyItem(TrackDailyBean bean) {
+Widget _buildMovingTrackDailyItem(TrackDailyBean bean,
+    {TrackItemClick? onItemClick}) {
   return Column(
     crossAxisAlignment: CrossAxisAlignment.start,
     children: [
@@ -67,28 +68,33 @@ Widget _buildMovingTrackDailyItem(TrackDailyBean bean) {
               ],
             ),
             Expanded(
-                child: Container(
-              height: 50.w,
-              margin: EdgeInsets.only(top: 26.w),
-              decoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(8.r),
-                  gradient: LinearGradient(colors: [
-                    '#F8F5FF'.color,
-                    ColorName.transparent,
-                  ])),
-              padding: EdgeInsets.symmetric(horizontal: 14.w),
-              child: Row(
-                children: [
-                  Assets.images.iconTrackMoving.image(width: 16.w),
-                  SizedBox(width: 5.w),
-                  Text(
-                    StringName.trackDetailMoving,
-                    style: TextStyle(
-                        fontSize: 12.sp,
-                        color: '#333333'.color,
-                        fontWeight: FontWeight.bold),
-                  )
-                ],
+                child: GestureDetector(
+              onTap: () {
+                onItemClick?.call(bean);
+              },
+              child: Container(
+                height: 50.w,
+                margin: EdgeInsets.only(top: 26.w),
+                decoration: BoxDecoration(
+                    borderRadius: BorderRadius.circular(8.r),
+                    gradient: LinearGradient(colors: [
+                      '#F8F5FF'.color,
+                      ColorName.transparent,
+                    ])),
+                padding: EdgeInsets.symmetric(horizontal: 14.w),
+                child: Row(
+                  children: [
+                    Assets.images.iconTrackMoving.image(width: 16.w),
+                    SizedBox(width: 5.w),
+                    Text(
+                      StringName.trackDetailMoving,
+                      style: TextStyle(
+                          fontSize: 12.sp,
+                          color: '#333333'.color,
+                          fontWeight: FontWeight.bold),
+                    )
+                  ],
+                ),
               ),
             ))
           ],
@@ -177,7 +183,7 @@ Widget buildStayTrackDailyItem(TrackDailyBean bean,
 }
 
 Widget buildErrorTrackDailyItem(TrackDailyBean bean,
-    {EdgeInsetsGeometry? contentPadding}) {
+    {EdgeInsetsGeometry? contentPadding, TrackItemClick? onItemClick}) {
   return Column(
     crossAxisAlignment: CrossAxisAlignment.start,
     children: [
@@ -203,39 +209,46 @@ Widget buildErrorTrackDailyItem(TrackDailyBean bean,
               ],
             ),
             Expanded(
-                child: Container(
-              height: 50.w,
-              padding: EdgeInsets.all(10.w),
-              margin: contentPadding ?? EdgeInsets.only(top: 41.w, bottom: 7.w),
-              decoration: BoxDecoration(
-                  borderRadius: BorderRadius.circular(8.r),
-                  gradient: LinearGradient(colors: [
-                    '#FFECEC'.color,
-                    ColorName.white,
-                  ])),
-              child: Row(
-                children: [
-                  Assets.images.iconTrackError.image(width: 19.4.w),
-                  SizedBox(width: 5.5.w),
-                  Text(StringName.trackDetailError,
-                      style: TextStyle(
-                          fontSize: 12.sp,
-                          color: '#333333'.color,
-                          fontWeight: FontWeight.bold)),
-                  SizedBox(width: 10.w),
-                  GestureDetector(
-                    onTap: () {
-                      TrackErrorTipsDialog.show();
-                    },
-                    child: Text(
-                      StringName.trackDetailSeeError,
-                      style: TextStyle(fontSize: 11.sp, color: '#4476FF'.color),
+                child: GestureDetector(
+              onTap: () {
+                onItemClick?.call(bean);
+              },
+              child: Container(
+                height: 50.w,
+                padding: EdgeInsets.all(10.w),
+                margin:
+                    contentPadding ?? EdgeInsets.only(top: 41.w, bottom: 7.w),
+                decoration: BoxDecoration(
+                    borderRadius: BorderRadius.circular(8.r),
+                    gradient: LinearGradient(colors: [
+                      '#FFECEC'.color,
+                      ColorName.white,
+                    ])),
+                child: Row(
+                  children: [
+                    Assets.images.iconTrackError.image(width: 19.4.w),
+                    SizedBox(width: 5.5.w),
+                    Text(StringName.trackDetailError,
+                        style: TextStyle(
+                            fontSize: 12.sp,
+                            color: '#333333'.color,
+                            fontWeight: FontWeight.bold)),
+                    SizedBox(width: 10.w),
+                    GestureDetector(
+                      onTap: () {
+                        TrackErrorTipsDialog.show();
+                      },
+                      child: Text(
+                        StringName.trackDetailSeeError,
+                        style:
+                            TextStyle(fontSize: 11.sp, color: '#4476FF'.color),
+                      ),
                     ),
-                  ),
-                  Spacer(),
-                  Assets.images.imgTrackAiAnalyse.image(width: 73.w),
-                  SizedBox(width: 6.w),
-                ],
+                    Spacer(),
+                    Assets.images.imgTrackAiAnalyse.image(width: 73.w),
+                    SizedBox(width: 6.w),
+                  ],
+                ),
               ),
             ))
           ],

+ 22 - 4
lib/module/track/track_day_detail/track_day_detail_controller.dart

@@ -156,8 +156,9 @@ class TrackDayDetailController extends BaseController {
             markerType: markerType,
             customAvatarUrl: customAvatarUrl));
       }
-      if (markers.last.markerType != MarkerType.traceEndMinePoint ||
-          markers.last.markerType != MarkerType.traceEndFriendPoint) {
+      if (markers.isNotEmpty &&
+          (markers.last.markerType != MarkerType.traceEndMinePoint ||
+              markers.last.markerType != MarkerType.traceEndFriendPoint)) {
         markers.last.markerType = trackController.userInfo?.isMine == true
             ? MarkerType.traceEndMinePoint
             : MarkerType.traceEndFriendPoint;
@@ -381,17 +382,34 @@ class TrackDayDetailController extends BaseController {
     if (bean.status == TrackStatus.stay) {
       //停留状态
       Marker selectMarker = Marker(
-        id: Constants.traceSelectId,
+        id: Constants.tracePopupId,
         markerName: '',
         latitude: bean.lat,
         longitude: bean.lng,
-        markerType: MarkerType.traceSelectPoint,
+        markerType: MarkerType.tracePopupPoint,
         popup: Popup(
           title: bean.addr ?? '',
           desc: TrackUtil.formatDurationFromMillis(bean.duration),
         ),
       );
       trackController.showSelectMarker(points, selectMarker);
+    } else if (bean.status == TrackStatus.moving) {
+      final movingPoints =
+          TrackUtil.getTrackMovePoints(trackOriginPoints, bean.start, bean.end);
+      trackController.showMovingTrack(movingPoints);
+    } else if (bean.status == TrackStatus.error) {
+      final errorPoints =
+          TrackUtil.getTrackMovePoints(trackOriginPoints, bean.start, bean.end);
+      if (errorPoints.isEmpty) {
+        return;
+      }
+      Marker errorMarker = Marker(
+          id: Constants.traceErrorId,
+          markerName: '',
+          latitude: errorPoints.first.latitude,
+          longitude: errorPoints.first.longitude,
+          markerType: MarkerType.trackErrorPoint);
+      trackController.showTrackError(errorPoints, errorMarker);
     }
   }
 

+ 6 - 4
lib/module/track/track_day_detail/track_day_detail_view.dart

@@ -284,11 +284,13 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
                       TrackExpandType.errorNow) {
                 return buildErrorTrackDailyItem(
                     controller.expandSituation!.second,
-                    contentPadding: EdgeInsets.only(top: 46.w, bottom: 12.w));
+                    contentPadding: EdgeInsets.only(top: 46.w, bottom: 12.w),
+                    onItemClick: controller.onHistoryTrackItemClick);
               } else {
                 return buildStayTrackDailyItem(
                     controller.expandSituation!.second,
-                    contentPadding: EdgeInsets.only(top: 35.w));
+                    contentPadding: EdgeInsets.only(top: 35.w),
+                    onItemClick: controller.onHistoryTrackItemClick);
               }
             } else {
               return SizedBox.shrink();
@@ -335,8 +337,8 @@ class TrackDayDetailView extends BaseView<TrackDayDetailController> {
                   children: [
                     Text(
                       controller.isExpanded
-                          ? StringName.trackDetailExpand
-                          : StringName.trackDetailFold,
+                          ? StringName.trackDetailFold
+                          : StringName.trackDetailExpand,
                       style: TextStyle(fontSize: 10.sp, color: '#666666'.color),
                     ),
                     SizedBox(width: 1.w),

+ 13 - 0
lib/module/track/track_util.dart

@@ -59,4 +59,17 @@ class TrackUtil {
     }
     return movePoints;
   }
+
+  static LatLng? getTrackStartPoint(
+      List<AtmobTrackPoint>? pointsList, int startTime) {
+    if (pointsList == null || pointsList.isEmpty) {
+      return null;
+    }
+    for (var point in pointsList) {
+      if (point.time >= startTime) {
+        return LatLng(latitude: point.latitude, longitude: point.longitude);
+      }
+    }
+    return null;
+  }
 }

+ 2 - 1
plugins/map/lib/flutter_map.dart

@@ -9,9 +9,10 @@ export 'package:flutter_map/src/core/flutter_map.dart';
 
 //公共配置.
 export 'package:flutter_map/src/consts/map_constants.dart';
+export 'package:flutter_map/src/consts/marker_type.dart';
+export 'package:flutter_map/src/consts/polyline_type.dart';
 
 //实体类
-export 'package:flutter_map/src/consts/marker_type.dart';
 export 'package:flutter_map/src/entity/marker.dart';
 export 'package:flutter_map/src/entity/camera_position.dart';
 export 'package:flutter_map/src/entity/map_location.dart';

+ 2 - 0
plugins/map/lib/src/consts/map_constants.dart

@@ -31,10 +31,12 @@ class MapConstants {
   static const String methodUpdateOrAddMarkers = "marker#updateOrAddMarkers";
   static const String methodReplaceAllMarkers = "marker#replaceAllMarkers";
   static const String methodMarkerOnTap = "marker#onTap";
+  static const String methodMarkerRemoveMarker = "marker#removeMarker";
 
   //轨迹纠偏
   static const String methodQueryProcessedTrace = "trace#queryProcessedTrace";
 
   //polyline
   static const String methodAddPolyline = "polyline#addPolyline";
+  static const String methodRemovePolyline = "polyline#removePolyline";
 }

+ 3 - 2
plugins/map/lib/src/consts/marker_type.dart

@@ -6,8 +6,9 @@ enum MarkerType {
   traceStartPoint(3),
   traceEndFriendPoint(4),
   traceEndMinePoint(5),
-  traceSelectPoint(6),
-  tracePassingPoint(7); //轨迹途径点样式
+  tracePopupPoint(6), //popup气泡样式
+  tracePassingPoint(7), //轨迹途径点样式
+  trackErrorPoint(8); //轨迹错误点样式
 
   final int value;
 

+ 9 - 0
plugins/map/lib/src/consts/polyline_type.dart

@@ -0,0 +1,9 @@
+enum PolylineType {
+  normal('normal'),
+  error('error'),
+  selected('selected');
+
+  final String value;
+
+  const PolylineType(this.value);
+}

+ 41 - 4
plugins/map/lib/src/core/map_controller.dart

@@ -13,6 +13,7 @@ import 'package:flutter_map/src/interface/map_fun_interface.dart';
 import 'package:flutter_map/src/interface/map_marker_interface.dart';
 import 'package:flutter_map/src/interface/map_polyline_interface.dart';
 
+import '../consts/polyline_type.dart';
 import '../entity/map_padding.dart';
 
 class MapController
@@ -119,12 +120,16 @@ class MapController
   }
 
   @override
-  void addPolyline(List<LatLng> points,
-      {bool isAnimateCamera = true, MapPadding? mapPadding}) {
+  void addPolyline(String lineId, List<LatLng> points,
+      {bool isAnimateCamera = true,
+      PolylineType lineType = PolylineType.normal,
+      MapPadding? mapPadding}) {
     if (_isDisposed || points.isEmpty) return;
     Map<String, dynamic> map = {};
+    map['lineId'] = lineId;
     map['points'] = _encodeJson(points);
     map['isAnimateCamera'] = isAnimateCamera;
+    map['lineType'] = lineType.value;
     if (mapPadding != null) {
       map['mapPadding'] = _encodeJson(mapPadding);
     }
@@ -170,16 +175,48 @@ class MapController
     }
   }
 
+  @override
+  void removeMarker(String markerId) {
+    if (_isDisposed || markerId.isEmpty) return;
+    final params = {
+      'method': MapConstants.methodMarkerRemoveMarker,
+      'args': {'markerId': markerId}
+    };
+    debugPrint("removeMarker...params==>$params");
+    if (_channel != null) {
+      _executeMethod(params);
+    } else {
+      _pendingOperations.add(params);
+    }
+  }
+
+  @override
+  void removePolyline(String lineId) {
+    if (_isDisposed || lineId.isEmpty) return;
+    final params = {
+      'method': MapConstants.methodRemovePolyline,
+      'args': {'lineId': lineId}
+    };
+    debugPrint("removePolyline...params==>$params");
+    if (_channel != null) {
+      _executeMethod(params);
+    } else {
+      _pendingOperations.add(params);
+    }
+  }
+
   /// iOS 需要一个Map 而不是json string
   dynamic _encodeJson(dynamic object) {
     // iOS平台直接返回对象或转换为JSON对象
     if (Platform.isIOS) {
       if (object is List) {
-        return object.map((item) => item is Codable ? item.toJson() : item).toList();
+        return object
+            .map((item) => item is Codable ? item.toJson() : item)
+            .toList();
       }
       return object is Codable ? object.toJson() : object;
     }
-    
+
     // 其他平台序列化为JSON字符串
     return jsonEncode(object);
   }

+ 3 - 0
plugins/map/lib/src/interface/map_marker_interface.dart

@@ -11,4 +11,7 @@ abstract class MapMarkerInterface {
   void replaceAllMarkers(List<Marker> markers);
 
   void clearAllMarkers();
+
+  //清除指定标记物
+  void removeMarker(String markerId);
 }

+ 6 - 2
plugins/map/lib/src/interface/map_polyline_interface.dart

@@ -1,9 +1,13 @@
 import 'package:flutter_map/src/entity/map_padding.dart';
 
 import '../../flutter_map.dart';
+import '../consts/polyline_type.dart';
 
 abstract class MapPolylineInterface {
   //画线   isAnimateCamera 是否动画移动到线的起点 ,mapPadding 地图边距 单位dp
-  void addPolyline(List<LatLng> points,
-      {bool isAnimateCamera = true, MapPadding? mapPadding});
+  void addPolyline(String lineId, List<LatLng> points,
+      {bool isAnimateCamera, PolylineType lineType, MapPadding? mapPadding});
+
+  //清除制定的线
+  void removePolyline(String lineId);
 }

+ 3 - 2
plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/bean/MakerInfo.java

@@ -102,15 +102,16 @@ public class MakerInfo {
     }
 
     @Retention(RetentionPolicy.SOURCE)
-    @IntDef({MarkerType.MINE, MarkerType.FRIEND, MarkerType.TRACE_START_POINT, MarkerType.TRACE_END_FRIEND_POINT, MarkerType.TRACE_END_MINE_POINT, MarkerType.TRACE_SELECT_POINT, MarkerType.TRACE_PASSING_POINT})
+    @IntDef({MarkerType.MINE, MarkerType.FRIEND, MarkerType.TRACE_START_POINT, MarkerType.TRACE_END_FRIEND_POINT, MarkerType.TRACE_END_MINE_POINT, MarkerType.TRACE_POPUP_POINT, MarkerType.TRACE_PASSING_POINT, MarkerType.TRACE_ERROR_POINT})
     public @interface MarkerType {
         int MINE = 1;
         int FRIEND = 2;
         int TRACE_START_POINT = 3;
         int TRACE_END_FRIEND_POINT = 4;
         int TRACE_END_MINE_POINT = 5;
-        int TRACE_SELECT_POINT = 6;
+        int TRACE_POPUP_POINT = 6;
         int TRACE_PASSING_POINT = 7;
+        int TRACE_ERROR_POINT = 8;
     }
 
 

+ 5 - 5
plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/contants/Constants.java

@@ -24,21 +24,19 @@ public class Constants {
     public static final String METHOD_START_LOCATION = "startLocation";//开启定位
 
 
-
     /**
      * 轨迹
      */
     public static final String METHOD_QUERY_PROCESSED_TRACE = "trace#queryProcessedTrace";
 
 
-
     /***********************************************地图操作相关********************************/
     public static final String METHOD_MOVE_CAMERA = "map#moveCamera";
     public static final String METHOD_ANIMATE_CAMERA = "map#animateCamera";
     public static final String METHOD_MAP_CLEAR = "map#clear";
     public static final String METHOD_MAP_MOVE_TO_SUITABLE_LOCATION = "map#moveToSuitableLocation";
 
-    public static final String[] METHOD_ID_LIST_FOR_MAP = {METHOD_MOVE_CAMERA, METHOD_ANIMATE_CAMERA,METHOD_MAP_CLEAR,METHOD_MAP_MOVE_TO_SUITABLE_LOCATION};
+    public static final String[] METHOD_ID_LIST_FOR_MAP = {METHOD_MOVE_CAMERA, METHOD_ANIMATE_CAMERA, METHOD_MAP_CLEAR, METHOD_MAP_MOVE_TO_SUITABLE_LOCATION};
 
     /**
      * markers
@@ -46,17 +44,19 @@ public class Constants {
     public static final String METHOD_UPDATE_OR_ADD_MARKERS = "marker#updateOrAddMarkers";
     public static final String METHOD_REPLACE_ALL_MARKERS = "marker#replaceAllMarkers";
     public static final String METHOD_MARKER_ON_TAP = "marker#onTap";
+    public static final String METHOD_REMOVE_MARKER = "marker#removeMarker";
 
 
-    public static final String[] METHOD_ID_LIST_FOR_MARKER = {METHOD_UPDATE_OR_ADD_MARKERS, METHOD_REPLACE_ALL_MARKERS, METHOD_MARKER_ON_TAP};
+    public static final String[] METHOD_ID_LIST_FOR_MARKER = {METHOD_UPDATE_OR_ADD_MARKERS, METHOD_REPLACE_ALL_MARKERS, METHOD_MARKER_ON_TAP, METHOD_REMOVE_MARKER};
 
 
     /**
      * 线
      */
     public static final String METHOD_UPDATE_OR_ADD_POLYLINE = "polyline#addPolyline";
+    public static final String METHOD_REMOVE_POLYLINE = "polyline#removePolyline";
 
-    public static final String[] METHOD_ID_LIST_FOR_POLYLINE = {METHOD_UPDATE_OR_ADD_POLYLINE};
+    public static final String[] METHOD_ID_LIST_FOR_POLYLINE = {METHOD_UPDATE_OR_ADD_POLYLINE, METHOD_REMOVE_POLYLINE};
 
 
 }

+ 35 - 5
plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/marker/MarkersController.java

@@ -6,7 +6,6 @@ import android.graphics.Canvas;
 import android.text.TextUtils;
 import android.view.LayoutInflater;
 import android.view.View;
-import android.widget.FrameLayout;
 
 import androidx.annotation.NonNull;
 import androidx.constraintlayout.widget.ConstraintLayout;
@@ -22,6 +21,7 @@ import com.atmob.map_amap_android.bean.MakerInfo;
 import com.atmob.map_amap_android.bean.Popup;
 import com.atmob.map_amap_android.contants.Constants;
 import com.atmob.map_amap_android.databinding.ItemLocationMarkerBinding;
+import com.atmob.map_amap_android.databinding.ItemTrackErrorMarkerBinding;
 import com.atmob.map_amap_android.databinding.ItemTrackPassingMarkerBinding;
 import com.atmob.map_amap_android.databinding.ItemTrackSelectedMarkerBinding;
 import com.atmob.map_amap_android.databinding.ItemTrackStartMarkerBinding;
@@ -30,12 +30,14 @@ import com.atmob.map_amap_android.util.BitmapCallback;
 import com.atmob.map_amap_android.util.GsonUtil;
 import com.atmob.map_amap_android.util.ImageCacheLoader;
 import com.atmob.map_amap_android.util.LogUtil;
+import com.atmob.map_amap_android.util.ParamUtil;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 
 import java.util.HashMap;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Map;
 import java.util.Objects;
 
 import io.flutter.plugin.common.MethodCall;
@@ -76,7 +78,31 @@ public class MarkersController implements MyMethodCallHandler, AMap.OnMarkerClic
             case Constants.METHOD_REPLACE_ALL_MARKERS:
                 replaceAllMarkers(call, result);
                 break;
+            case Constants.METHOD_REMOVE_MARKER:
+                removeMarker(call, result);
+                break;
+        }
+    }
+
+
+    private void removeMarker(MethodCall call, MethodChannel.Result result) {
+        LogUtil.i(TAG, "removeMarker===>" + call.arguments());
+        Map<String, Object> arguments = call.arguments();
+        if (arguments == null || arguments.isEmpty()) {
+            result.error("-1", "removeMarker.arguments is empty", null);
+            return;
+        }
+        String markerId = ParamUtil.getString(arguments, "markerId");
+        if (TextUtils.isEmpty(markerId)) {
+            result.error("-1", "removeMarker.markerId is empty", null);
+            return;
+        }
+        Marker marker = currentMarkers.get(markerId);
+        if (marker != null) {
+            marker.remove();
+            currentMarkers.remove(markerId);
         }
+        result.success(null);
     }
 
     private void replaceAllMarkers(MethodCall call, MethodChannel.Result result) {
@@ -158,7 +184,7 @@ public class MarkersController implements MyMethodCallHandler, AMap.OnMarkerClic
             Object object = marker.getObject();
             if (object instanceof MakerInfo) {
                 MakerInfo cacheInfo = (MakerInfo) object;
-                if (cacheInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_SELECT_POINT) {
+                if (cacheInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_POPUP_POINT) {
                     boolean popupChanged = !Objects.equals(cacheInfo.getPopup(), makerInfo.getPopup());
                     if (popupChanged) {
                         BitmapDescriptor markerBitmap = getMarkerBitmap(makerInfo, null);
@@ -235,9 +261,9 @@ public class MarkersController implements MyMethodCallHandler, AMap.OnMarkerClic
                 .icon(markerBitmap)
                 .anchor(0.5f, 0.9f);
 
-        if (makerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_PASSING_POINT) {
+        if (makerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_PASSING_POINT || makerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_ERROR_POINT) {
             markerOption.anchor(0.5f, 0.5f);
-        } else if (makerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_SELECT_POINT) {
+        } else if (makerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_POPUP_POINT) {
             markerOption.anchor(0.5f, 1.1f);
         }
 
@@ -293,7 +319,7 @@ public class MarkersController implements MyMethodCallHandler, AMap.OnMarkerClic
             ItemTrackPassingMarkerBinding trackPassingMarkerBinding = ItemTrackPassingMarkerBinding.inflate(LayoutInflater.from(context));
             ConstraintLayout view = trackPassingMarkerBinding.getRoot();
             return viewGetBitmapDescriptor(view);
-        } else if (markerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_SELECT_POINT) {
+        } else if (markerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_POPUP_POINT) {
             ItemTrackSelectedMarkerBinding trackSelectedMarkerBinding = ItemTrackSelectedMarkerBinding.inflate(LayoutInflater.from(context));
             Popup popup = markerInfo.getPopup();
             if (popup != null) {
@@ -302,6 +328,10 @@ public class MarkersController implements MyMethodCallHandler, AMap.OnMarkerClic
             }
             ConstraintLayout view = trackSelectedMarkerBinding.getRoot();
             return viewGetBitmapDescriptor(view);
+        } else if (markerInfo.getMarkerType() == MakerInfo.MarkerType.TRACE_ERROR_POINT) {
+            ItemTrackErrorMarkerBinding trackPassingMarkerBinding = ItemTrackErrorMarkerBinding.inflate(LayoutInflater.from(context));
+            ConstraintLayout view = trackPassingMarkerBinding.getRoot();
+            return viewGetBitmapDescriptor(view);
         }
         return null;
     }

+ 44 - 5
plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/polyline/PolylineController.java

@@ -23,8 +23,10 @@ import com.atmob.map_amap_android.util.SizeUtil;
 import com.google.gson.Gson;
 import com.google.gson.reflect.TypeToken;
 
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 
 import io.flutter.plugin.common.MethodCall;
 import io.flutter.plugin.common.MethodChannel;
@@ -38,6 +40,8 @@ public class PolylineController implements MyMethodCallHandler {
 
     private final Context context;
 
+    private final HashMap<String, Polyline> currentPolylineMap = new HashMap<>(10);
+
     private final MethodChannel methodChannel;
     private final Gson gson;
 
@@ -55,6 +59,30 @@ public class PolylineController implements MyMethodCallHandler {
             case Constants.METHOD_UPDATE_OR_ADD_POLYLINE:
                 addPolyline(call, result);
                 break;
+            case Constants.METHOD_REMOVE_POLYLINE:
+                removePolyLine(call, result);
+                break;
+        }
+    }
+
+    private void removePolyLine(MethodCall call, MethodChannel.Result result) {
+        try {
+            Map<String, Object> arguments = call.arguments();
+            if (arguments == null) {
+                result.error("arguments is null", null, null);
+                return;
+            }
+            String lineId = ParamUtil.getString(arguments, "lineId");
+            LogUtil.d(TAG, "removePolyline lineId===>" + lineId);
+            Polyline polyline = currentPolylineMap.get(lineId);
+            if (polyline != null) {
+                polyline.remove();
+                currentPolylineMap.remove(lineId);
+            }
+            result.success(null);
+        } catch (Exception e) {
+            LogUtil.d(TAG, "removePolyline error===>" + e.getMessage());
+            result.error("JsonSyntaxException", e.getMessage(), null);
         }
     }
 
@@ -65,6 +93,7 @@ public class PolylineController implements MyMethodCallHandler {
                 result.error("arguments is null", null, null);
                 return;
             }
+            String lineId = ParamUtil.getString(arguments, "lineId");
             boolean isAnimateCamera = ParamUtil.getBoolean(arguments, "isAnimateCamera", true);
             LogUtil.d(TAG, "isAnimateCamera===>" + isAnimateCamera);
             String points = (String) arguments.get("points");
@@ -79,7 +108,8 @@ public class PolylineController implements MyMethodCallHandler {
                 result.error("latLngList is empty", null, null);
                 return;
             }
-            drawTrackByPoints(latLngList);
+            String lineType = ParamUtil.getString(arguments, "lineType");
+            drawTrackByPoints(lineId, latLngList, lineType);
             if (isAnimateCamera) {
                 String paddingStr = (String) arguments.get("mapPadding");
 
@@ -97,12 +127,20 @@ public class PolylineController implements MyMethodCallHandler {
         }
     }
 
-    private Polyline drawTrackByPoints(List<LatLng> points) {
+    private void drawTrackByPoints(String lineId, List<LatLng> points, @PolylineType String lineType) {
         if (map == null || points == null || points.isEmpty()) {
-            return null;
+            return;
+        }
+        int lineDrawableId;
+        if (Objects.equals(PolylineType.ERROR, lineType)) {
+            lineDrawableId = R.drawable.bg_map_error_line;
+        } else if (Objects.equals(PolylineType.SELECTED, lineType)) {
+            lineDrawableId = R.drawable.bg_map_selected_line;
+        } else {
+            lineDrawableId = R.drawable.bg_map_line;
         }
         PolylineOptions polylineOptions = new PolylineOptions()
-                .setCustomTexture(BitmapDescriptorFactory.fromResource(R.drawable.bg_map_line))
+                .setCustomTexture(BitmapDescriptorFactory.fromResource(lineDrawableId))
                 .setUseTexture(true)
                 .width(SizeUtil.dp2px(context, 8));
 
@@ -115,7 +153,8 @@ public class PolylineController implements MyMethodCallHandler {
                 lastPoint = currentPoint;
             }
         }
-        return map.addPolyline(polylineOptions);
+        Polyline polyline = map.addPolyline(polylineOptions);
+        currentPolylineMap.put(lineId, polyline);
     }
 
     private void moveToSuitableLocation(List<LatLng> points, MapPadding padding) {

+ 15 - 0
plugins/map_amap_android/android/src/main/java/com/atmob/map_amap_android/overlays/polyline/PolylineType.java

@@ -0,0 +1,15 @@
+package com.atmob.map_amap_android.overlays.polyline;
+
+import androidx.annotation.StringDef;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.SOURCE)
+@StringDef({PolylineType.NORMAL, PolylineType.ERROR, PolylineType.SELECTED})
+public @interface PolylineType {
+
+    String NORMAL = "normal";
+    String ERROR = "error";
+    String SELECTED = "selected";
+}

BIN
plugins/map_amap_android/android/src/main/res/drawable-xxhdpi/bg_map_error_line.webp


BIN
plugins/map_amap_android/android/src/main/res/drawable-xxhdpi/bg_map_selected_line.webp


+ 6 - 0
plugins/map_amap_android/android/src/main/res/drawable/bg_track_error_point.xml

@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <corners android:radius="100dp" />
+    <solid android:color="#2BFF5555" />
+</shape>

+ 9 - 0
plugins/map_amap_android/android/src/main/res/drawable/icon_marker_error.xml

@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="utf-8"?>
+<shape xmlns:android="http://schemas.android.com/apk/res/android"
+    android:shape="oval">
+    <corners android:radius="100dp" />
+    <solid android:color="#FF5555" />
+    <stroke
+        android:width="2dp"
+        android:color="#fff" />
+</shape>

+ 35 - 0
plugins/map_amap_android/android/src/main/res/layout/item_track_error_marker.xml

@@ -0,0 +1,35 @@
+<?xml version="1.0" encoding="utf-8"?>
+<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <View
+        android:id="@+id/v_bg1"
+        android:layout_width="30dp"
+        android:layout_height="30dp"
+        android:background="@drawable/bg_track_error_point"
+        app:layout_constraintBottom_toBottomOf="parent"
+        app:layout_constraintEnd_toEndOf="parent"
+        app:layout_constraintStart_toStartOf="parent"
+        app:layout_constraintTop_toTopOf="parent" />
+
+    <View
+        android:id="@+id/v_bg2"
+        android:layout_width="22dp"
+        android:layout_height="22dp"
+        android:background="@drawable/bg_track_error_point"
+        app:layout_constraintBottom_toBottomOf="@+id/v_bg1"
+        app:layout_constraintEnd_toEndOf="@+id/v_bg1"
+        app:layout_constraintStart_toStartOf="@+id/v_bg1"
+        app:layout_constraintTop_toTopOf="@+id/v_bg1" />
+
+    <View
+        android:layout_width="14dp"
+        android:layout_height="14dp"
+        android:background="@drawable/icon_marker_error"
+        app:layout_constraintBottom_toBottomOf="@+id/v_bg2"
+        app:layout_constraintEnd_toEndOf="@+id/v_bg2"
+        app:layout_constraintStart_toStartOf="@+id/v_bg2"
+        app:layout_constraintTop_toTopOf="@+id/v_bg2" />
+</androidx.constraintlayout.widget.ConstraintLayout>

+ 0 - 1
plugins/map_amap_android/android/src/main/res/layout/item_track_selected_marker.xml

@@ -24,7 +24,6 @@
             android:id="@+id/tv_popup_title"
             android:layout_width="wrap_content"
             android:layout_height="wrap_content"
-            android:layout_marginHorizontal="14dp"
             android:textColor="#333333"
             android:textSize="11sp"
             app:layout_constraintEnd_toEndOf="parent"