I need to show location A and the location B by pulse animation. I am able to achieve that using the below code. But the problem I am facing is the GroundOverlay changes its size when the zoom level changes. If the location A and B are close to each other(i.e the map zoom in level is high) the radius of the pulse is too big. When I zoom out then it becomes too small.
How can I keep the size of the overlay same irrespective of the zoom level of the map.
The below code is referred from here: Animated Transparent Circle on Google Maps v2 is NOT animating correctly
private void showRipples(LatLng latLng, int color) {
GradientDrawable d = new GradientDrawable();
d.setShape(GradientDrawable.OVAL);
d.setSize(500, 500);
d.setColor(ContextCompat.getColor(Activity.this, color));
d.setStroke(0, Color.TRANSPARENT);
final Bitmap bitmap = Bitmap.createBitmap(d.getIntrinsicWidth()
, d.getIntrinsicHeight()
, Bitmap.Config.ARGB_8888);
// Convert the drawable to bitmap
final Canvas canvas = new Canvas(bitmap);
d.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
d.draw(canvas);
// Radius of the circle
final int radius = getResources().getDimensionPixelSize(R.dimen.ripple_radius);
// Add the circle to the map
final GroundOverlay circle = googleMap.addGroundOverlay(new GroundOverlayOptions()
.position(latLng, 2 * radius).image(BitmapDescriptorFactory.fromBitmap(bitmap)));
// Prep the animator
PropertyValuesHolder radiusHolder = PropertyValuesHolder.ofFloat("radius", 1, radius);
PropertyValuesHolder transparencyHolder = PropertyValuesHolder.ofFloat("transparency", 0, 1);
ValueAnimator valueAnimator = new ValueAnimator();
valueAnimator.setRepeatCount(ValueAnimator.INFINITE);
valueAnimator.setRepeatMode(ValueAnimator.RESTART);
valueAnimator.setValues(radiusHolder, transparencyHolder);
valueAnimator.setDuration(DURATION);
valueAnimator.setEvaluator(new FloatEvaluator());
valueAnimator.setInterpolator(new AccelerateDecelerateInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
@Override
public void onAnimationUpdate(ValueAnimator valueAnimator) {
float animatedRadius = (float) valueAnimator.getAnimatedValue("radius");
float animatedAlpha = (float) valueAnimator.getAnimatedValue("transparency");
circle.setDimensions(animatedRadius * 2);
circle.setTransparency(animatedAlpha);
}
});
// start the animation
valueAnimator.start();
}
[this is what I get when the two locations are far from each other][]1
If the two locations are close to each other I get this behaviour
For the first image if I zoom in, then I do see the pulse animation.
Is there a way I can keep the radius of the pulse same irrespective of the zoom level ?
This happens because
GroundOverlay
is zoomed together with the google map. To avoid that you should recreate overlay for each zoom level with corrected radius for that zoom level and latitude (meters_to_pixels
in example source code). For avoidGroundOverlay
recreation you should store createdGroundOverlay
object and remove it before creating new. For that you need some changes in yourshowRipples()
method - it should returns created overlay. Full source code for example with one marker:So let's say you want the overlay circle radius to be a fixed dimension (relative to screen pixels) for example 1/10th of the screen width (at the current zoom).
This example uses width as the scaling axis but you could just as well use height or diagonal (by using different points of the projection).
The use of 'far' can be replaced with 'near' - it is used to account for tilt so you'll have to experiment.
So now your resource value is a scaling factor and not an absolute radius value - so for this example you would set the resource value to 0.10F and use that where's it hard-coded above.
If you want the pulse (and overlay) to work after/during zoom then you'll need to update the width of the overlay circle (circle.setWidth(scaledRadius)) using the 'onCameraIdle' event - using the same computation as above for scaledRadius, such as: