Skip to content

Commit f2f1859

Browse files
committed
feat: added method to stop animation
1 parent ab13a7e commit f2f1859

File tree

4 files changed

+99
-4
lines changed

4 files changed

+99
-4
lines changed

library/src/main/java/com/google/maps/android/clustering/view/ClusterRenderer.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,11 @@ public interface ClusterRenderer<T extends ClusterItem> {
5858
*/
5959
void setAnimationDuration(long animationDurationMs);
6060

61+
/**
62+
* Stops all animations
63+
*/
64+
void stopAnimation();
65+
6166
/**
6267
* Called when the view is added.
6368
*/

library/src/main/java/com/google/maps/android/clustering/view/ClusterRendererMultipleItems.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -543,6 +543,13 @@ public void setAnimationDuration(long animationDurationMs) {
543543
mAnimationDurationMs = animationDurationMs;
544544
}
545545

546+
@Override
547+
public void stopAnimation() {
548+
for (AnimationTask animation : ongoingAnimations) {
549+
animation.cancel();
550+
}
551+
}
552+
546553
private static double distanceSquared(Point a, Point b) {
547554
return (a.x - b.x) * (a.x - b.x) + (a.y - b.y) * (a.y - b.y);
548555
}

library/src/main/java/com/google/maps/android/clustering/view/DefaultAdvancedMarkersClusterRenderer.java

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ public class DefaultAdvancedMarkersClusterRenderer<T extends ClusterItem> implem
8383
private boolean mAnimate;
8484
private long mAnimationDurationMs;
8585
private final Executor mExecutor = Executors.newSingleThreadExecutor();
86+
private final Queue<AnimationTask> ongoingAnimations = new LinkedList<>();
8687

8788
private static final int[] BUCKETS = {10, 20, 50, 100, 200, 500, 1000};
8889
private ShapeDrawable mColoredCircleBackground;
@@ -568,6 +569,13 @@ public void setAnimation(boolean animate) {
568569
mAnimate = animate;
569570
}
570571

572+
@Override
573+
public void stopAnimation() {
574+
for (AnimationTask animation : ongoingAnimations) {
575+
animation.cancel();
576+
}
577+
}
578+
571579
/**
572580
* {@inheritDoc} The default duration is 300 milliseconds.
573581
*
@@ -671,7 +679,17 @@ public void remove(boolean priority, Marker m) {
671679
*/
672680
public void animate(MarkerWithPosition marker, LatLng from, LatLng to) {
673681
lock.lock();
674-
mAnimationTasks.add(new AnimationTask(marker, from, to));
682+
AnimationTask task = new AnimationTask(marker, from, to);
683+
684+
for (AnimationTask existingTask : ongoingAnimations) {
685+
if (existingTask.marker.getId().equals(task.marker.getId())) {
686+
existingTask.cancel();
687+
break;
688+
}
689+
}
690+
691+
mAnimationTasks.add(task);
692+
ongoingAnimations.add(task);
675693
lock.unlock();
676694
}
677695

@@ -686,6 +704,14 @@ public void animate(MarkerWithPosition marker, LatLng from, LatLng to) {
686704
public void animateThenRemove(MarkerWithPosition marker, LatLng from, LatLng to) {
687705
lock.lock();
688706
AnimationTask animationTask = new AnimationTask(marker, from, to);
707+
for (AnimationTask existingTask : ongoingAnimations) {
708+
if (existingTask.marker.getId().equals(animationTask.marker.getId())) {
709+
existingTask.cancel();
710+
break;
711+
}
712+
}
713+
714+
ongoingAnimations.add(animationTask);
689715
animationTask.removeOnAnimationComplete(mClusterManager.getMarkerManager());
690716
mAnimationTasks.add(animationTask);
691717
lock.unlock();
@@ -1135,6 +1161,7 @@ private class AnimationTask extends AnimatorListenerAdapter implements ValueAnim
11351161
private final LatLng to;
11361162
private boolean mRemoveOnComplete;
11371163
private MarkerManager mMarkerManager;
1164+
private ValueAnimator valueAnimator;
11381165

11391166
private AnimationTask(MarkerWithPosition markerWithPosition, LatLng from, LatLng to) {
11401167
this.markerWithPosition = markerWithPosition;
@@ -1143,8 +1170,19 @@ private AnimationTask(MarkerWithPosition markerWithPosition, LatLng from, LatLng
11431170
this.to = to;
11441171
}
11451172

1173+
public void cancel() {
1174+
if (Looper.myLooper() != Looper.getMainLooper()) {
1175+
new Handler(Looper.getMainLooper()).post(this::cancel);
1176+
return;
1177+
}
1178+
markerWithPosition.position = to;
1179+
mRemoveOnComplete = false;
1180+
valueAnimator.cancel();
1181+
ongoingAnimations.remove(this);
1182+
}
1183+
11461184
public void perform() {
1147-
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
1185+
valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
11481186
valueAnimator.setInterpolator(ANIMATION_INTERP);
11491187
valueAnimator.setDuration(mAnimationDurationMs);
11501188
valueAnimator.addUpdateListener(this);
@@ -1160,6 +1198,8 @@ public void onAnimationEnd(Animator animation) {
11601198
mMarkerManager.remove(marker);
11611199
}
11621200
markerWithPosition.position = to;
1201+
valueAnimator.cancel();
1202+
ongoingAnimations.remove(this);
11631203
}
11641204

11651205
public void removeOnAnimationComplete(MarkerManager markerManager) {

library/src/main/java/com/google/maps/android/clustering/view/DefaultClusterRenderer.java

Lines changed: 45 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ public class DefaultClusterRenderer<T extends ClusterItem> implements ClusterRen
8282
private boolean mAnimate;
8383
private long mAnimationDurationMs;
8484
private final Executor mExecutor = Executors.newSingleThreadExecutor();
85+
private final Queue<AnimationTask> ongoingAnimations = new LinkedList<>();
8586

8687
private static final int[] BUCKETS = {10, 20, 50, 100, 200, 500, 1000};
8788
private ShapeDrawable mColoredCircleBackground;
@@ -569,6 +570,13 @@ public void setAnimationDuration(long animationDurationMs) {
569570
mAnimationDurationMs = animationDurationMs;
570571
}
571572

573+
@Override
574+
public void stopAnimation() {
575+
for (AnimationTask animation : ongoingAnimations) {
576+
animation.cancel();
577+
}
578+
}
579+
572580
private Set<? extends Cluster<T>> immutableOf(Set<? extends Cluster<T>> clusters) {
573581
return clusters != null ? Collections.unmodifiableSet(clusters) : Collections.emptySet();
574582
}
@@ -662,7 +670,17 @@ public void remove(boolean priority, Marker m) {
662670
*/
663671
public void animate(MarkerWithPosition marker, LatLng from, LatLng to) {
664672
lock.lock();
665-
mAnimationTasks.add(new AnimationTask(marker, from, to));
673+
AnimationTask task = new AnimationTask(marker, from, to);
674+
675+
for (AnimationTask existingTask : ongoingAnimations) {
676+
if (existingTask.marker.getId().equals(task.marker.getId())) {
677+
existingTask.cancel();
678+
break;
679+
}
680+
}
681+
682+
mAnimationTasks.add(task);
683+
ongoingAnimations.add(task);
666684
lock.unlock();
667685
}
668686

@@ -677,6 +695,14 @@ public void animate(MarkerWithPosition marker, LatLng from, LatLng to) {
677695
public void animateThenRemove(MarkerWithPosition marker, LatLng from, LatLng to) {
678696
lock.lock();
679697
AnimationTask animationTask = new AnimationTask(marker, from, to);
698+
for (AnimationTask existingTask : ongoingAnimations) {
699+
if (existingTask.marker.getId().equals(animationTask.marker.getId())) {
700+
existingTask.cancel();
701+
break;
702+
}
703+
}
704+
705+
ongoingAnimations.add(animationTask);
680706
animationTask.removeOnAnimationComplete(mClusterManager.getMarkerManager());
681707
mAnimationTasks.add(animationTask);
682708
lock.unlock();
@@ -1125,6 +1151,7 @@ private class AnimationTask extends AnimatorListenerAdapter implements ValueAnim
11251151
private final LatLng to;
11261152
private boolean mRemoveOnComplete;
11271153
private MarkerManager mMarkerManager;
1154+
private ValueAnimator valueAnimator;
11281155

11291156
private AnimationTask(MarkerWithPosition markerWithPosition, LatLng from, LatLng to) {
11301157
this.markerWithPosition = markerWithPosition;
@@ -1134,14 +1161,26 @@ private AnimationTask(MarkerWithPosition markerWithPosition, LatLng from, LatLng
11341161
}
11351162

11361163
public void perform() {
1137-
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
1164+
valueAnimator = ValueAnimator.ofFloat(0.0f, 1.0f);
11381165
valueAnimator.setInterpolator(ANIMATION_INTERP);
11391166
valueAnimator.setDuration(mAnimationDurationMs);
11401167
valueAnimator.addUpdateListener(this);
11411168
valueAnimator.addListener(this);
11421169
valueAnimator.start();
11431170
}
11441171

1172+
public void cancel() {
1173+
if (Looper.myLooper() != Looper.getMainLooper()) {
1174+
new Handler(Looper.getMainLooper()).post(this::cancel);
1175+
return;
1176+
}
1177+
markerWithPosition.position = to;
1178+
mRemoveOnComplete = false;
1179+
valueAnimator.cancel();
1180+
ongoingAnimations.remove(this);
1181+
}
1182+
1183+
11451184
@Override
11461185
public void onAnimationEnd(Animator animation) {
11471186
if (mRemoveOnComplete) {
@@ -1150,13 +1189,17 @@ public void onAnimationEnd(Animator animation) {
11501189
mMarkerManager.remove(marker);
11511190
}
11521191
markerWithPosition.position = to;
1192+
1193+
// Remove the task from the queue
1194+
ongoingAnimations.remove(this);
11531195
}
11541196

11551197
public void removeOnAnimationComplete(MarkerManager markerManager) {
11561198
mMarkerManager = markerManager;
11571199
mRemoveOnComplete = true;
11581200
}
11591201

1202+
11601203
@Override
11611204
public void onAnimationUpdate(ValueAnimator valueAnimator) {
11621205
if (to == null || from == null || marker == null) {

0 commit comments

Comments
 (0)