diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt index e7fcfad..00778a9 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt @@ -46,7 +46,7 @@ params.height = ((getScreenHeight() * 0.7).toInt()) window.attributes = params - val id = intent.getStringExtra(Constant.INTENT_PARAM)!! + val id = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! try { marker = DataBaseManager.get.queryMarkerById(id).first() binding.objectTypeView.text = diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt index e7fcfad..00778a9 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt @@ -46,7 +46,7 @@ params.height = ((getScreenHeight() * 0.7).toInt()) window.attributes = params - val id = intent.getStringExtra(Constant.INTENT_PARAM)!! + val id = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! try { marker = DataBaseManager.get.queryMarkerById(id).first() binding.objectTypeView.text = diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt index 7b50f58..e359965 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt @@ -42,7 +42,7 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import kotlinx.coroutines.Dispatchers @@ -96,7 +96,7 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - val flag = intent.getStringExtra(Constant.INTENT_PARAM) as String + val flag = intent.getStringExtra(Constant.INTENT_PARAM_KEY) as String isExecuteTask = flag != "0" //绑定串口通信服务 @@ -180,7 +180,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() serialPortService?.closeSerialPort() "标识器深度探测超时,请移动位置重试".show(context) lifecycleScope.launch(Dispatchers.Main) { @@ -208,7 +208,7 @@ searchMarker() } } else { - LoadingDialogHub.show(this, "正在探测标识器埋深,请稍后...") + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") countDownTimer.start() // 发送读取标识器埋设深度指令 serialPortService?.openSerialPort( @@ -217,7 +217,7 @@ val hex = buffer.toHex() if (hex.startsWith("53")) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() showDepthDialog(hex) } @@ -226,7 +226,7 @@ }) } } else { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) lifecycleScope.launch(Dispatchers.Main) { delay(300) diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt index e7fcfad..00778a9 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt @@ -46,7 +46,7 @@ params.height = ((getScreenHeight() * 0.7).toInt()) window.attributes = params - val id = intent.getStringExtra(Constant.INTENT_PARAM)!! + val id = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! try { marker = DataBaseManager.get.queryMarkerById(id).first() binding.objectTypeView.text = diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt index 7b50f58..e359965 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt @@ -42,7 +42,7 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import kotlinx.coroutines.Dispatchers @@ -96,7 +96,7 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - val flag = intent.getStringExtra(Constant.INTENT_PARAM) as String + val flag = intent.getStringExtra(Constant.INTENT_PARAM_KEY) as String isExecuteTask = flag != "0" //绑定串口通信服务 @@ -180,7 +180,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() serialPortService?.closeSerialPort() "标识器深度探测超时,请移动位置重试".show(context) lifecycleScope.launch(Dispatchers.Main) { @@ -208,7 +208,7 @@ searchMarker() } } else { - LoadingDialogHub.show(this, "正在探测标识器埋深,请稍后...") + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") countDownTimer.start() // 发送读取标识器埋设深度指令 serialPortService?.openSerialPort( @@ -217,7 +217,7 @@ val hex = buffer.toHex() if (hex.startsWith("53")) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() showDepthDialog(hex) } @@ -226,7 +226,7 @@ }) } } else { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) lifecycleScope.launch(Dispatchers.Main) { delay(300) diff --git a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt index 4067968..054a810 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt @@ -29,7 +29,7 @@ import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import java.io.File @@ -53,14 +53,14 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "事件上报中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "事件上报中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "事件上报成功!".show(this) finish() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt index e7fcfad..00778a9 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt @@ -46,7 +46,7 @@ params.height = ((getScreenHeight() * 0.7).toInt()) window.attributes = params - val id = intent.getStringExtra(Constant.INTENT_PARAM)!! + val id = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! try { marker = DataBaseManager.get.queryMarkerById(id).first() binding.objectTypeView.text = diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt index 7b50f58..e359965 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt @@ -42,7 +42,7 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import kotlinx.coroutines.Dispatchers @@ -96,7 +96,7 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - val flag = intent.getStringExtra(Constant.INTENT_PARAM) as String + val flag = intent.getStringExtra(Constant.INTENT_PARAM_KEY) as String isExecuteTask = flag != "0" //绑定串口通信服务 @@ -180,7 +180,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() serialPortService?.closeSerialPort() "标识器深度探测超时,请移动位置重试".show(context) lifecycleScope.launch(Dispatchers.Main) { @@ -208,7 +208,7 @@ searchMarker() } } else { - LoadingDialogHub.show(this, "正在探测标识器埋深,请稍后...") + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") countDownTimer.start() // 发送读取标识器埋设深度指令 serialPortService?.openSerialPort( @@ -217,7 +217,7 @@ val hex = buffer.toHex() if (hex.startsWith("53")) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() showDepthDialog(hex) } @@ -226,7 +226,7 @@ }) } } else { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) lifecycleScope.launch(Dispatchers.Main) { delay(300) diff --git a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt index 4067968..054a810 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt @@ -29,7 +29,7 @@ import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import java.io.File @@ -53,14 +53,14 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "事件上报中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "事件上报中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "事件上报成功!".show(this) finish() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt index f29eb76..f4aadf8 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt @@ -21,7 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +90,8 @@ override fun observeRequestState() { versionViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "检查版本中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "检查版本中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/build.gradle b/app/build.gradle index c58b092..4df8a01 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -77,7 +77,7 @@ dependencies { //基础依赖库 - implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.0.11' + implementation 'com.github.AndroidCoderPeng:Kotlin-lite-lib:1.1.0' implementation 'androidx.core:core-ktx:1.9.0' implementation 'androidx.appcompat:appcompat:1.6.1' //Google官方授权框架 diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 3021b54..30d92f9 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -97,7 +97,7 @@ + android:value="81d6d9fb2997ea43c27abe88f29050ca" /> clusterItems; private Marker marker; - public Cluster(LatLng latLng) { + public Cluster(LatLng latLng, String title) { this.latLng = latLng; + this.title = title; clusterItems = new ArrayList<>(); } @@ -29,6 +31,10 @@ return latLng; } + public String getTitle() { + return title; + } + public void setMarker(Marker marker) { this.marker = marker; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java index 6f36bd6..92916a4 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterItem.java @@ -7,4 +7,9 @@ * 返回聚合元素的地理位置 */ LatLng getPosition(); + + /** + * 返回聚合点标题(ID代替) + */ + String getTitle(); } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java deleted file mode 100644 index 045cdc9..0000000 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOnClickListener.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.casic.common.detector.gd.cluster; - -import com.amap.api.maps.model.Marker; - -import java.util.List; - -public interface ClusterOnClickListener { - /** - * 点击聚合点的回调处理函数 - * - * @param marker 点击的聚合点 - * @param items 聚合点所包含的元素 - */ - void onClick(Marker marker, List items); -} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java index 26d8cc5..b3e9a09 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/ClusterOverlay.java @@ -1,6 +1,7 @@ package com.casic.common.detector.gd.cluster; import android.content.Context; +import android.graphics.Bitmap; import android.graphics.Color; import android.os.Handler; import android.os.HandlerThread; @@ -10,6 +11,7 @@ import android.view.Gravity; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.collection.LruCache; import com.amap.api.maps.AMap; @@ -34,10 +36,10 @@ public class ClusterOverlay implements AMap.OnCameraChangeListener, AMap.OnMarkerClickListener { private final AMap amap; private final Context context; - private final List clusterItems; + private final CopyOnWriteArrayList clusterItems; private final List clusters; private final int clusterSize; - private ClusterOnClickListener clusterClickListener; + private OnClickClusterListener clickClusterListener; private ClusterRender clusterRender; private final CopyOnWriteArrayList addMarkers = new CopyOnWriteArrayList<>(); private double clusterDistance; @@ -60,15 +62,20 @@ /** * 构造函数,批量添加聚合元素时,调用此构造函数 */ - public ClusterOverlay(Context context, AMap amap, List clusterItems, int clusterSize) { + public ClusterOverlay(Context context, AMap amap, CopyOnWriteArrayList clusterItems, int clusterSize) { //默认最多会缓存80张图片作为聚合显示元素图片,根据自己显示需求和app使用内存情况,可以修改数量 this.lruCache = new LruCache(80) { + protected void entryRemoved(boolean evicted, @NonNull Integer key, @NonNull BitmapDescriptor oldValue, BitmapDescriptor newValue) { + recycleBitmap(oldValue.getBitmap()); + } }; + if (clusterItems != null) { this.clusterItems = clusterItems; } else { - this.clusterItems = new ArrayList<>(); + this.clusterItems = new CopyOnWriteArrayList<>(); } + this.context = context; this.clusters = new ArrayList<>(); this.amap = amap; @@ -81,11 +88,20 @@ assignClusters(); } + private void recycleBitmap(Bitmap bitmap) { + if (bitmap == null) { + return; + } + if (!bitmap.isRecycled()) { + bitmap.recycle(); + } + } + /** * 设置聚合点的点击事件 */ - public void setOnClusterClickListener(ClusterOnClickListener clusterClickListener) { - this.clusterClickListener = clusterClickListener; + public void setOnClickClusterListener(OnClickClusterListener clickClusterListener) { + this.clickClusterListener = clickClusterListener; } /** @@ -140,12 +156,12 @@ @Override public boolean onMarkerClick(Marker arg0) { - if (clusterClickListener == null) { + if (clickClusterListener == null) { return true; } Cluster cluster = (Cluster) arg0.getObject(); if (cluster != null) { - clusterClickListener.onClick(arg0, cluster.getClusterItems()); + clickClusterListener.onClick(arg0, cluster.getClusterItems()); return true; } return false; @@ -156,7 +172,8 @@ * 将聚合元素添加至地图上 */ private void addClusterToMap(List clusters) { - ArrayList removeMarkers = new ArrayList<>(addMarkers); + CopyOnWriteArrayList removeMarkers = new CopyOnWriteArrayList<>(addMarkers); + removeMarkers.addAll(addMarkers); AlphaAnimation alphaAnimation = new AlphaAnimation(1, 0); RemoveAnimationListener removeAnimationListener = new RemoveAnimationListener(removeMarkers); for (Marker marker : removeMarkers) { @@ -176,11 +193,10 @@ private void addSingleClusterToMap(Cluster cluster) { LatLng latlng = cluster.getCenterLatLng(); MarkerOptions markerOptions = new MarkerOptions(); - markerOptions.icon(getBitmapDes(cluster.getClusterCount())).position(latlng); + markerOptions.icon(getBitmapDescriptor(cluster.getClusterCount())).position(latlng); Marker marker = amap.addMarker(markerOptions); marker.setAnimation(addAnimation); marker.setObject(cluster); - marker.startAnimation(); cluster.setMarker(marker); addMarkers.add(marker); @@ -198,7 +214,7 @@ if (visibleBounds.contains(latlng)) { Cluster cluster = getCluster(latlng, clusters); if (cluster == null) { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); } cluster.addClusterItem(clusterItem); @@ -245,7 +261,7 @@ markerHandler.removeMessages(MarkerHandler.UPDATE_SINGLE_CLUSTER); markerHandler.sendMessageDelayed(message, 5); } else { - cluster = new Cluster(latlng); + cluster = new Cluster(latlng, clusterItem.getTitle()); clusters.add(cluster); cluster.addClusterItem(clusterItem); Message message = Message.obtain(); @@ -273,7 +289,7 @@ /** * 获取每个聚合点的绘制样式 */ - private BitmapDescriptor getBitmapDes(int num) { + private BitmapDescriptor getBitmapDescriptor(int num) { BitmapDescriptor bitmapDescriptor = lruCache.get(num); if (bitmapDescriptor == null) { TextView textView = new TextView(context); @@ -285,7 +301,7 @@ textView.setTextColor(Color.WHITE); textView.setTextSize(TypedValue.COMPLEX_UNIT_SP, 16); if (clusterRender != null && clusterRender.getDrawableByCount(num) != null) { - textView.setBackgroundDrawable(clusterRender.getDrawableByCount(num)); + textView.setBackground(clusterRender.getDrawableByCount(num)); } else { textView.setBackgroundResource(R.mipmap.defaultcluster); } @@ -301,7 +317,7 @@ */ private void updateCluster(Cluster cluster) { Marker marker = cluster.getMarker(); - marker.setIcon(getBitmapDes(cluster.getClusterCount())); + marker.setIcon(getBitmapDescriptor(cluster.getClusterCount())); } /** @@ -320,7 +336,6 @@ } public void handleMessage(Message message) { - switch (message.what) { case ADD_CLUSTER_LIST: List clusters = (List) message.obj; diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java new file mode 100644 index 0000000..ac5adae --- /dev/null +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/OnClickClusterListener.java @@ -0,0 +1,15 @@ +package com.casic.common.detector.gd.cluster; + +import com.amap.api.maps.model.Marker; + +import java.util.List; + +public interface OnClickClusterListener { + /** + * 点击聚合点的回调处理函数 + * + * @param marker 点击的聚合点 + * @param clusterItems 聚合点所包含的元素 + */ + void onClick(Marker marker, List clusterItems); +} diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java index fb4e952..dbd9b26 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RegionItem.java @@ -16,6 +16,7 @@ return latLng; } + @Override public String getTitle() { return title; } diff --git a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java index f66d352..89c4945 100644 --- a/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java +++ b/app/src/main/java/com/casic/common/detector/gd/cluster/RemoveAnimationListener.java @@ -4,14 +4,15 @@ import com.amap.api.maps.model.animation.Animation; import java.util.List; +import java.util.concurrent.CopyOnWriteArrayList; /** * marker渐变动画,动画结束后将Marker删除 */ public class RemoveAnimationListener implements Animation.AnimationListener { - private final List removeMarkers; + private final CopyOnWriteArrayList removeMarkers; - public RemoveAnimationListener(List removeMarkers) { + public RemoveAnimationListener(CopyOnWriteArrayList removeMarkers) { this.removeMarkers = removeMarkers; } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt index ca859aa..3129710 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/InstallMarkerActivity.kt @@ -52,7 +52,7 @@ import com.pengxh.kt.lite.extensions.timestampToTime import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.TitleBarView import java.io.File @@ -254,7 +254,7 @@ //读标识器 binding.readMarkerButton.setOnClickListener { - LoadingDialogHub.show(this, "标识器读取中,请稍后...") + LoadingDialog.show(this, "标识器读取中,请稍后...") countDownTimer.start() binding.readMarkerButton.isEnabled = false serialPortService?.openSerialPort(arrayListOf('2'), this) @@ -268,7 +268,7 @@ val markerId = hex.take(20).hexToString() if (markerId.isNumber()) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() serialPortService?.closeSerialPort() binding.readMarkerButton.isEnabled = true @@ -286,7 +286,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "读取此标识器ID超时,请重试".show(context) binding.readMarkerButton.isEnabled = true serialPortService?.closeSerialPort() @@ -406,15 +406,15 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "标识器安装中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "标识器安装中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() clearDefaultData() "安装成功".show(this) } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt index d57a772..1a73443 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/LoginActivity.kt @@ -10,7 +10,7 @@ import com.pengxh.kt.lite.base.KotlinBaseActivity import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog @@ -87,8 +87,8 @@ override fun observeRequestState() { userViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "登录中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "登录中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt index dd90638..d91361f 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/MainActivity.kt @@ -29,6 +29,7 @@ import com.amap.api.maps.model.BitmapDescriptorFactory import com.amap.api.maps.model.LatLng import com.amap.api.maps.model.LatLngBounds +import com.amap.api.maps.model.Marker import com.amap.api.maps.model.MarkerOptions import com.amap.api.maps.model.MyLocationStyle import com.casic.common.detector.gd.R @@ -40,6 +41,8 @@ import com.casic.common.detector.gd.callback.OnSerialPortListener import com.casic.common.detector.gd.cluster.ClusterItem import com.casic.common.detector.gd.cluster.ClusterOverlay +import com.casic.common.detector.gd.cluster.ClusterRender +import com.casic.common.detector.gd.cluster.OnClickClusterListener import com.casic.common.detector.gd.cluster.RegionItem import com.casic.common.detector.gd.databinding.ActivityMainBinding import com.casic.common.detector.gd.extensions.appendDownloadUrl @@ -76,7 +79,7 @@ import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.utils.WeakReferenceHandler import com.pengxh.kt.lite.widget.TitleBarView @@ -88,9 +91,11 @@ import kotlinx.coroutines.launch import kotlinx.coroutines.withContext import java.io.File +import java.util.concurrent.CopyOnWriteArrayList -class MainActivity : KotlinBaseActivity(), OnSerialPortListener, - Handler.Callback { + +class MainActivity : KotlinBaseActivity(), ClusterRender, + OnClickClusterListener, OnSerialPortListener, Handler.Callback { //TODO 此代码正式版删除 companion object { @@ -100,7 +105,6 @@ private val kTag = "MainActivity" private val context = this private val samplePopupWindow by lazy { SamplePopupWindow(this) } - private val regionRadius by lazy { LocaleConstant.RADIUS_SIZE.dp2px(this) } private val backDrawables by lazy { HashMap() } private val detailDialog by lazy { MarkerDetailDialog(this) } private val locationTool by lazy { LocationTool(this) } @@ -110,7 +114,6 @@ private val soundPool = SoundPool.Builder().setMaxStreams(16).setAudioAttributes(attr).build() private var clickTime: Long = 0 private var markers = ArrayList() - private var clusterOverlay: ClusterOverlay? = null private var isFreeTask = false private var freeTaskTitle = "" private var ids = HashSet() @@ -174,7 +177,7 @@ DataBaseManager.get.saveMarkerInLocale(marker) } } - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() showLabelsOnMap() } } @@ -568,9 +571,9 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "提交工单中,请稍后") + LoadState.Loading -> LoadingDialog.show(this, "提交工单中,请稍后") - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } @@ -651,127 +654,145 @@ "工单下载成功!".show(this) } - private fun showLabelsOnMap() { - clusterOverlay?.onDestroy() - val clusterItems = ArrayList() + private var clusterOverlay: ClusterOverlay? = null + private fun showLabelsOnMap() { + val clusterItems = CopyOnWriteArrayList() + if (clusterOverlay == null) { + clusterOverlay = ClusterOverlay( + this, aMap, clusterItems, LocaleConstant.RADIUS_SIZE.dp2px(this) + ) + } + clusterOverlay?.apply { + setClusterRender(this@MainActivity) + setOnClickClusterListener(this@MainActivity) + } markers.forEach { if (it.lat.isNotEmpty() && it.lng.isNotEmpty()) { val latitude = it.lat.toDouble() val longitude = it.lng.toDouble() val latLng = LatLng(latitude, longitude, false) - val regionItem = RegionItem(latLng, it.id.toString()) + //用标识器的ID当作地图Marker的Title + val regionItem = RegionItem(latLng, it.markerId.toString()) clusterItems.add(regionItem) } } + } - clusterOverlay = ClusterOverlay(this, aMap, clusterItems, regionRadius) - clusterOverlay?.setClusterRender { clusterNum -> - val radius = 80.dp2px(this) - if (clusterNum == 0) { - var bitmapDrawable = backDrawables[0] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[0] = bitmapDrawable - } + override fun getDrawableByCount(clusterNum: Int): Drawable { + //聚合点圆形半径 + val radius = 80.dp2px(this) + if (clusterNum == 1) { + var bitmapDrawable = backDrawables[1] + if (bitmapDrawable == null) { + bitmapDrawable = R.mipmap.label.convertDrawable(this)!! + backDrawables[1] = bitmapDrawable } - if (clusterNum == 1) { - var bitmapDrawable = backDrawables[1] - if (bitmapDrawable == null) { - bitmapDrawable = R.mipmap.label.convertDrawable(this)!! - backDrawables[1] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 5) { - var bitmapDrawable = backDrawables[2] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(159, 100, 149, 237)) - ) - backDrawables[2] = bitmapDrawable - } - bitmapDrawable - } else if (clusterNum < 10) { - var bitmapDrawable = backDrawables[3] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(199, 30, 144, 255)) - ) - backDrawables[3] = bitmapDrawable - } - bitmapDrawable - } else { - var bitmapDrawable = backDrawables[4] - if (bitmapDrawable == null) { - bitmapDrawable = BitmapDrawable( - null, radius.drawCircle(Color.argb(235, 65, 105, 225)) - ) - backDrawables[4] = bitmapDrawable - } - bitmapDrawable + return bitmapDrawable + } else if (clusterNum < 5) { + var bitmapDrawable = backDrawables[2] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(159, 100, 149, 237)) + ) + backDrawables[2] = bitmapDrawable } + return bitmapDrawable + } else if (clusterNum < 10) { + var bitmapDrawable = backDrawables[3] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(199, 30, 144, 255)) + ) + backDrawables[3] = bitmapDrawable + } + return bitmapDrawable + } else { + var bitmapDrawable = backDrawables[4] + if (bitmapDrawable == null) { + bitmapDrawable = BitmapDrawable( + null, radius.drawCircle(Color.argb(235, 65, 105, 225)) + ) + backDrawables[4] = bitmapDrawable + } + return bitmapDrawable } - clusterOverlay?.setOnClusterClickListener { _, items -> - var item: RegionItem? = null - val builder = LatLngBounds.Builder() - for (clusterItem in items) { - builder.include(clusterItem.position) - item = clusterItem as RegionItem + } + + override fun onClick(marker: Marker, clusterItems: MutableList) { + if (clusterItems.size == 1) { + val clusterItem = clusterItems[0] + showNavigationOption(clusterItem.title, clusterItem.position) + } else { + //聚合点,显示聚合点列表 + val idArray = ArrayList() + for (clusterItem in clusterItems) { + idArray.add(clusterItem.title) } - - if (item == null) { - "标识器经纬度异常".show(this) - return@setOnClusterClickListener - } - - val latLng = LatLng(item.position.latitude, item.position.longitude) - - //移动视图 - val latLngBounds = builder.build() - aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) - - AlertControlDialog.Builder().setContext(this).setTitle("提示") - .setMessage("请选择操作方式").setNegativeButton("标识器信息") - .setPositiveButton("到这里去").setOnDialogButtonClickListener(object : - AlertControlDialog.OnDialogButtonClickListener { - override fun onConfirmClick() { - RouteOnMap.startNavigation(context, item.title, latLng) - } - - override fun onCancelClick() { - markers.forEach { - if (it.id.toString() == item.title) { - navigatePageTo(it.markerId) - } - } + BottomActionSheet.Builder() + .setContext(this) + .setItemTextColor(Color.BLUE) + .setActionItemTitle(idArray) + .setOnActionSheetListener(object : BottomActionSheet.OnActionSheetListener { + override fun onActionItemClick(position: Int) { + val markerId = idArray[position] + //根据markerId找到标识器 + val bean = markers.find { x -> x.markerId == markerId }!! + showNavigationOption( + bean.markerId, LatLng(bean.lat.toDouble(), bean.lng.toDouble()) + ) } }).build().show() } } + private fun showNavigationOption(title: String, latLng: LatLng) { + //移动视图 + val builder = LatLngBounds.Builder() + builder.include(latLng) + val latLngBounds = builder.build() + aMap.animateCamera(CameraUpdateFactory.newLatLngBounds(latLngBounds, 0)) + + //显示导航选项 + AlertControlDialog.Builder() + .setContext(this) + .setTitle("提示") + .setMessage("请选择操作方式") + .setNegativeButton("标识器信息") + .setPositiveButton("到这里去") + .setOnDialogButtonClickListener(object : + AlertControlDialog.OnDialogButtonClickListener { + override fun onConfirmClick() { + RouteOnMap.startNavigation(context, title, latLng) + } + + override fun onCancelClick() { + navigatePageTo(title) + } + }).build().show() + } + private fun detectRedrawGraphic(task: TaskDetailLocalModel) { task.markerModels.forEach { val latLng = LatLng(it.lat, it.lng) - val otMarkerOptions = MarkerOptions() - otMarkerOptions.position(latLng) - otMarkerOptions.visible(true) // 设置可见 + val markerOptions = MarkerOptions() + markerOptions.position(latLng) + markerOptions.visible(true) // 设置可见 if (it.isDetected == "0") { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_red1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } else { - otMarkerOptions.icon( + markerOptions.icon( BitmapDescriptorFactory.fromBitmap( BitmapFactory.decodeResource(resources, R.mipmap.label_blue1) ) - ).period(99).title("工单标识器").snippet(it.markerId) + ).title(it.markerId) } - aMap.addMarker(otMarkerOptions) + aMap.addMarker(markerOptions) } showLabelsOnMap() } @@ -786,7 +807,7 @@ if (isNetworkConnected()) { val companyId = SaveKeyValues.getValue(LocaleConstant.USER_COMPANY_ID, "") - LoadingDialogHub.show(this@MainActivity, "获取标识器信息中,请稍后") + LoadingDialog.show(this@MainActivity, "获取标识器信息中,请稍后") /** * 后台设计如此,都传companyId * */ @@ -830,7 +851,7 @@ val markers = DataBaseManager.get.queryMarkerByState("0") if (markers.isNotEmpty()) { //TODO 逻辑没梳理明白 -// LoadingDialogHub.show(this, "标识器补全中,请稍后...") +// LoadingDialog.show(this, "标识器补全中,请稍后...") // markers.forEach { marker -> // taskViewModel.installLabel( // this, @@ -863,7 +884,7 @@ // arrayListOf() // ) // } -// LoadingDialogHub.dismiss() +// LoadingDialog.dismiss() } else { "没有需要补传的标识器!".show(this) } @@ -907,6 +928,7 @@ override fun onDestroy() { super.onDestroy() + clusterOverlay?.onDestroy() binding.mapView.onDestroy() soundPool.autoPause() serialPortService?.closeSerialPort() diff --git a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt index fbdb4d0..69615bc 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/NewObjectDetailActivity.kt @@ -35,7 +35,7 @@ params.height = ((getScreenHeight() * 0.3).toInt()) window.attributes = params - val identifierId = intent.getStringExtra(Constant.INTENT_PARAM)!! + val identifierId = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! binding.identifierIdView.text = identifierId } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt index e7fcfad..00778a9 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/ObjectDetailActivity.kt @@ -46,7 +46,7 @@ params.height = ((getScreenHeight() * 0.7).toInt()) window.attributes = params - val id = intent.getStringExtra(Constant.INTENT_PARAM)!! + val id = intent.getStringExtra(Constant.INTENT_PARAM_KEY)!! try { marker = DataBaseManager.get.queryMarkerById(id).first() binding.objectTypeView.text = diff --git a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt index 7b50f58..e359965 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/SearchMarkerActivity.kt @@ -42,7 +42,7 @@ import com.pengxh.kt.lite.extensions.navigatePageTo import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.Constant -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import com.pengxh.kt.lite.widget.dialog.AlertMessageDialog import kotlinx.coroutines.Dispatchers @@ -96,7 +96,7 @@ } override fun initOnCreate(savedInstanceState: Bundle?) { - val flag = intent.getStringExtra(Constant.INTENT_PARAM) as String + val flag = intent.getStringExtra(Constant.INTENT_PARAM_KEY) as String isExecuteTask = flag != "0" //绑定串口通信服务 @@ -180,7 +180,7 @@ } override fun onFinish() { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() serialPortService?.closeSerialPort() "标识器深度探测超时,请移动位置重试".show(context) lifecycleScope.launch(Dispatchers.Main) { @@ -208,7 +208,7 @@ searchMarker() } } else { - LoadingDialogHub.show(this, "正在探测标识器埋深,请稍后...") + LoadingDialog.show(this, "正在探测标识器埋深,请稍后...") countDownTimer.start() // 发送读取标识器埋设深度指令 serialPortService?.openSerialPort( @@ -217,7 +217,7 @@ val hex = buffer.toHex() if (hex.startsWith("53")) { runOnUiThread { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() countDownTimer.cancel() showDepthDialog(hex) } @@ -226,7 +226,7 @@ }) } } else { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "标识器未安装,安装成功后才可读取埋深!".show(this) lifecycleScope.launch(Dispatchers.Main) { delay(300) diff --git a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt index 4067968..054a810 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/UploadEventActivity.kt @@ -29,7 +29,7 @@ import com.pengxh.kt.lite.extensions.timestampToCompleteDate import com.pengxh.kt.lite.extensions.toJson import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.utils.SaveKeyValues import java.io.File @@ -53,14 +53,14 @@ override fun observeRequestState() { taskViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "事件上报中,请稍后...") + LoadState.Loading -> LoadingDialog.show(this, "事件上报中,请稍后...") LoadState.Success -> { - LoadingDialogHub.dismiss() + LoadingDialog.dismiss() "事件上报成功!".show(this) finish() } - else -> LoadingDialogHub.dismiss() + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt index f29eb76..f4aadf8 100644 --- a/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt +++ b/app/src/main/java/com/casic/common/detector/gd/view/VersionControlActivity.kt @@ -21,7 +21,7 @@ import com.pengxh.kt.lite.extensions.show import com.pengxh.kt.lite.utils.FileDownloadManager import com.pengxh.kt.lite.utils.LoadState -import com.pengxh.kt.lite.utils.LoadingDialogHub +import com.pengxh.kt.lite.utils.LoadingDialog import com.pengxh.kt.lite.widget.TitleBarView import com.pengxh.kt.lite.widget.dialog.AlertControlDialog import java.io.File @@ -90,8 +90,8 @@ override fun observeRequestState() { versionViewModel.loadState.observe(this) { when (it) { - LoadState.Loading -> LoadingDialogHub.show(this, "检查版本中,请稍后") - else -> LoadingDialogHub.dismiss() + LoadState.Loading -> LoadingDialog.show(this, "检查版本中,请稍后") + else -> LoadingDialog.dismiss() } } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 84c8776..7efb447 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1,5 +1,5 @@ - 探测仪 + 探测仪(GD) 中国航天科工集团二院二〇三所 数据加载中… 中国航天科工集团二院二〇三所 版权所有