I want to add a pulse ring animation on blue dot current user location in Android google mapFragment (like Uber).
Can anybody help me with this thing?
I have found a solution to add pulsating animation to a marker. Here is the map part, Here variable "map" denotes your map.
private Circle lastUserCircle;
private long pulseDuration = 1000;
private ValueAnimator lastPulseAnimator;
private void addPulsatingEffect(LatLng userLatlng){
if(lastPulseAnimator != null){
lastPulseAnimator.cancel();
Log.d("onLocationUpdated: ","cancelled" );
}
if(lastUserCircle != null)
lastUserCircle.setCenter(userLatlng);
lastPulseAnimator = valueAnimate(userLocation.getAccuracy(), pulseDuration, new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator animation) {
if(lastUserCircle != null)
lastUserCircle.setRadius((Float) animation.getAnimatedValue());
else {
lastUserCircle = map.addCircle(new CircleOptions()
.center(userLatlng)
.radius((Float) animation.getAnimatedValue())
.strokeColor(Color.RED)
.fillColor(Color.BLUE));
}
}
});
}
protected ValueAnimator valueAnimate(float accuracy,long duration, ValueAnimator.AnimatorUpdateListener updateListener){
Log.d( "valueAnimate: ", "called");
ValueAnimator va = ValueAnimator.ofFloat(0,accuracy);
va.setDuration(duration);
va.addUpdateListener(updateListener);
va.setRepeatCount(ValueAnimator.INFINITE);
va.setRepeatMode(ValueAnimator.RESTART);
va.start();
return va;
}
You have to call this on location updates by adding PositionChangedListener. You can easily find that in Google map docs. After that, for each update call the above method.
Fixing the pulse radius to somewhat same value, so that it's neither too big, nor too small
Write this method
protected float getDisplayPulseRadius(float radius) {
float diff = (map.getMaxZoomLevel() - map.getCameraPosition().zoom);
if (diff < 3)
return radius;
if (diff < 3.7)
return radius * (diff / 2);
if (diff < 4.5)
return (radius * diff);
if (diff < 5.5)
return (radius * diff) * 1.5f;
if (diff < 7)
return (radius * diff) * 2f;
if (diff < 7.8)
return (radius * diff) * 3.5f;
if (diff < 8.5)
return (float) (radius * diff) * 5;
if (diff < 10)
return (radius * diff) * 10f;
if (diff < 12)
return (radius * diff) * 18f;
if (diff < 13)
return (radius * diff) * 28f;
if (diff < 16)
return (radius * diff) * 40f;
if (diff < 18)
return (radius * diff) * 60;
return (radius * diff) * 80;
}
And change this line
userLocation.getAccuracy()
to
getDisplayPulseRadius(userLocation.getAccuracy()
And also
.radius((Float) animation.getAnimatedValue())
to
.radius(getDisplayPulseRadius((Float) animation.getAnimatedValue()))
If you want an effect like the color fades to transparent when it gets big, you can use this just in the next line where you are setting the radius inside the animator
circle.setFillColor(adjustAlpha(pulseAroundMeFillColor, 1 - animation.getAnimatedFraction()));
private int adjustAlpha(int color, float factor) {
int alpha = Math.round(Color.alpha(color) * factor);
int red = Color.red(color);
int green = Color.green(color);
int blue = Color.blue(color);
return Color.argb(alpha, red, green, blue);
}