Search code examples
androidanimationgoogle-maps-markersgoogle-maps-android-api-2android-maps

Cannot run multiple animations on GroundOverlay [GoogleMap]


I am trying to achieve a breathing effect animation on my MapFragment but for some reason, I cannot run multiple animations on the map. What I am trying to achieve is something like this:

enter image description here

And the circles are expanding gradually and fading away doing so. Right now my animation is doing this:

enter image description here

Which is not quite what I want. The current code (if I uncomment the 2 blocks with the handlers) is doing only one animation and the rest of the shapes are staying stationary. EDIT I found out what is going on - the "startAnimation" method is overriding the current animation. Now I am wondering if there is a way how I can avoid this overriding? Any ideas?:

enter image description here

This is my code:

   @Override
    public void onMapReady(GoogleMap googleMap) {
        mMap = googleMap;

//Add smallest image drawable overlay

        mDotMarkerBitmap = generateBitmapFromDrawable(R.drawable.circle_drawable);
        groundOverlay = mMap.addGroundOverlay(new GroundOverlayOptions()
                .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap))
                .position(xDesign, 100));
        groundAnimation = new RadiusAnimation(groundOverlay);
        groundAnimation.setRepeatCount(Animation.INFINITE);
        groundAnimation.setRepeatMode(Animation.RESTART);
        groundAnimation.setDuration(2000);
        mapFragment.getView().startAnimation(groundAnimation); // MapView where i show my map
//TODO  Fix the animation tomorrow
//Add medium size image drawable overlay

//        new Handler().postDelayed(new Runnable() {
//            @Override
//            public void run() {
//                // your code here
//                mDotMarkerBitmap = generateBitmapFromDrawable(R.drawable.circle_drawable2);
//                groundOverlay = mMap.addGroundOverlay(new GroundOverlayOptions()
//                        .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap))
//                        .position(xDesign, 100));
//                groundAnimation = new RadiusAnimation(groundOverlay);
//                groundAnimation.setRepeatCount(Animation.INFINITE);
//                groundAnimation.setRepeatMode(Animation.RESTART);
//                groundAnimation.setDuration(10000);
//                mapFragment.getView().startAnimation(groundAnimation); // MapView where i show my map
//            }
//        }, 1000/* 1sec delay */);

//
////Add smallest size image drawable overlay
//        new Handler().postDelayed(new Runnable()
//        {
//            @Override
//            public void run()
//            {
//                // your code here
//                mDotMarkerBitmap = generateBitmapFromDrawable(R.drawable.circle_drawable3);
//                groundOverlay = mMap.addGroundOverlay(new GroundOverlayOptions()
//                        .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap))
//                        .position(xDesign, 100));
//                groundAnimation = new RadiusAnimation(groundOverlay);
//                groundAnimation.setRepeatCount(Animation.INFINITE);
//                groundAnimation.setRepeatMode(Animation.RESTART);
//                groundAnimation.setDuration(2000);
//                mapFragment.getView().startAnimation(groundAnimation); // MapView where i show my map
//            }
//        }, 1000/* 1sec delay */);



        mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(xDesign, 15));
    }

circle_drawable.xml (circle_drawable2 and 3 are the same exept the width&height values, they are bigger 60 and 90dp and the colors - blue and red):

<?xml version="1.0" encoding="utf-8"?>
<shape
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="oval">
    <solid
        android:color="#0093e8"/>
    <size
        android:width="30dp"
        android:height="30dp"/>
</shape>

RadiusAnimation class:

public class RadiusAnimation extends Animation {
    private GroundOverlay groundOverlay;

    public RadiusAnimation(GroundOverlay groundOverlay) {
        this.groundOverlay = groundOverlay;

    }
    @Override
    protected void applyTransformation(float interpolatedTime, Transformation t) {
        groundOverlay.setDimensions( (100 * interpolatedTime) );
        groundOverlay.setTransparency( interpolatedTime );

    }


    @Override
    public void initialize(int width, int height, int parentWidth,int parentHeight) {
        super.initialize(width, height, parentWidth, parentHeight);
    }
}

Solution

  • In case someone is trying to do something similar I found the solution. In order to run multiple animations at the same, I can use AnimationSet. So I removed the Handlers which were to delay the individual animations but since each one is overriding the last one it was not working and I was seeing the last one added playing on the mapFragment. So I changed my code like that:

    public void onMapReady(GoogleMap googleMap) {
            mMap = googleMap;
    
    
    //Add smallest image drawable overlay
    
            Bitmap mDotMarkerBitmap1 = generateBitmapFromDrawable(R.drawable.circle_drawable);
    
            GroundOverlay groundOverlay1 = mMap.addGroundOverlay(new GroundOverlayOptions()
                    .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap1))
                    .position(xDesign, 100));
    
            groundAnimation = new RadiusAnimation(groundOverlay1);
            groundAnimation.setRepeatCount(Animation.INFINITE);
            groundAnimation.setRepeatMode(Animation.RESTART);
            //        groundAnimation.setDuration(700);
            breadingAnimations.addAnimation(groundAnimation);
    
    
            Bitmap mDotMarkerBitmap2 = generateBitmapFromDrawable(R.drawable.circle_drawable2);
            GroundOverlay groundOverlay2 = mMap.addGroundOverlay(new GroundOverlayOptions()
                    .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap2))
                    .position(xDesign, 100));
    
            Animation groundAnimation2 = new RadiusAnimation(groundOverlay2);
            groundAnimation2.setRepeatCount(Animation.INFINITE);
            groundAnimation2.setRepeatMode(Animation.RESTART);
            //        groundAnimation2.setDuration(900);
            breadingAnimations.addAnimation(groundAnimation2);
    
    
            Bitmap mDotMarkerBitmap3 = generateBitmapFromDrawable(R.drawable.circle_drawable3);
            GroundOverlay groundOverlay3 = mMap.addGroundOverlay(new GroundOverlayOptions()
                    .image(BitmapDescriptorFactory.fromBitmap(mDotMarkerBitmap3))
                    .position(xDesign, 100));
            Animation groundAnimation3 = new RadiusAnimation(groundOverlay3);
            groundAnimation2.setRepeatCount(Animation.INFINITE);
            groundAnimation2.setRepeatMode(Animation.RESTART);
            //        groundAnimation2.setDuration(1100);
            breadingAnimations.addAnimation(groundAnimation3);
    
            mapFragment.getView().startAnimation(breadingAnimations); // start animation
    
    
            mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(xDesign, 15));
        }