How to smoothly keep moving current location marker in Google Maps v2 android

14,352

Solution 1

Hi I have also the same thing in one of my project and it works like charm.

Add the below piece of code after this line :

marker.setPosition(new LatLng(lat, lng));

 //this code
 if (googleMap != null)
         googleMap.animateCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(lat, lng), 15.0f));

Hope it will help you. Thanks

Solution 2

You'll have to use an interpolator a linear or maybe an acceleration interpolator between the new latlng of the location and the current latlng of the marker. Here's an example with a bounce interpolator.

final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        final long duration = 2500;

        final Interpolator interpolator = new BounceInterpolator();
        marker.setVisible(true);

        handler.post(new Runnable() {
            @Override
            public void run() {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = Math.max(
                        1 - interpolator.getInterpolation((float) elapsed
                                / duration), 0);

                marker.setAnchor(0.5f, 1.0f + 6 * t);
                marker.setPosition(latlng)

                if (t > 0.0) {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                }
            }
        });
Share:
14,352
TheDevMan
Author by

TheDevMan

Updated on June 17, 2022

Comments

  • TheDevMan
    TheDevMan almost 2 years

    I have placed a marker for my location. I would like to move my marker smoothly something like the Google maps app. The blue circle moves very smoothly when I keep moving in my car. I would like implement the same for my app. how do I implement this on my app?

    As of now my location marker just jumps for different location on very location change and marks the marker there.

    Here is what I have don:

     googleMap.setMyLocationEnabled(true);
    

    So onMyLocationChange method is called automatically:

    @Override
    public void onMyLocationChange(Location location) 
    {
        curlat = location.getLatitude();
        curlong = location.getLongitude();
    
        if (markermylocation != null)
        {
            markermylocation.remove();
        }
    
            curlat = location.getLatitude();
            curlong = location.getLongitude();
            myLocation(curlat, curlong, username, imageURL, ZOOMVALUE);
    }
    

    in mylocaiton method:

    private void myLocation(double lat, double lng, String name, String url, float zoom)
    {
        if(firsttime  == 1)
        {
            LatLng ll = new LatLng(lat,lng);
            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(ll, zoom);
            googleMap.animateCamera(update);
            firsttime = 0;
        }
    
        final String uname = name; 
        curlat = lat;
        curlong = lng;
        LatLng position = new LatLng(curlat, curlong);
    
        markerOptionsmylocaiton = new MarkerOptions().position(position).icon(BitmapDescriptorFactory.fromBitmap(icon)).title(uname).anchor(0.5f, 1f);
        markermylocation = googleMap.addMarker(markerOptionsmylocaiton);
    
        LatLng latlang = new LatLng(curlat, curlong);
        animateMarker(markermylocation, latlang, false);
    }
    

    So everytime mylocation is called the marker gets removed and calls mylocation method and then creates the marker in the new postition. Instead I would like to get a smooth transition of the marker like Google maps? How to implement this?

    Update:

    After working couple of times on this: I came to this code finally but then my markers are not showing up:

    I am using the below method and calling this every time in myLocation method.

    public void animateMarker(final Marker marker, final LatLng toPosition,
            final boolean hideMarker) 
    {
        final Handler handler = new Handler();
        final long start = SystemClock.uptimeMillis();
        Projection proj = googleMap.getProjection();
        Point startPoint = proj.toScreenLocation(marker.getPosition());
        final LatLng startLatLng = proj.fromScreenLocation(startPoint);
        final long duration = 500;
    
        final Interpolator interpolator = new LinearInterpolator();
    
        handler.post(new Runnable() 
        {
            @Override
            public void run() 
            {
                long elapsed = SystemClock.uptimeMillis() - start;
                float t = interpolator.getInterpolation((float) elapsed
                        / duration);
                double lng = t * toPosition.longitude + (1 - t)
                        * startLatLng.longitude;
                double lat = t * toPosition.latitude + (1 - t)
                        * startLatLng.latitude;
                marker.setPosition(new LatLng(lat, lng));
    
                if (t < 1.0) 
                {
                    // Post again 16ms later.
                    handler.postDelayed(this, 16);
                } 
                else 
                {
                    if (hideMarker) 
                    {
                        marker.setVisible(false);
                    } 
                    else 
                    {
                        marker.setVisible(true);
                    }
                }
            }
        });
    }
    

    Thanks!

  • TheDevMan
    TheDevMan over 9 years
    Thanks for the quick reply. Let me work this and get back. I am surprised is that difficult to make a smooth move of marker. :(
  • danny117
    danny117 over 9 years
    The runnable is friend for making simple animations. Yes its tricky not difficult. You can easily change the marker latlng. marker.setPosition(latlng) but it will also be somewhat clunky.
  • TheDevMan
    TheDevMan over 9 years
    Finally got a chance to work on this. I used your logic + other reference came up with the above code. The problem is that when use it I don't see my marker at all. it comes up and just goes away. Please take a look at my code. Let me know where could be the problem? Thanks!
  • danny117
    danny117 over 9 years
    I think it would be something like double lng = t * (toPosition.longitude - startpos.longitude) + startpos.longitude; If you think it through... interpolation starts at zero and goes to 1. so when you get zero the formula becomes 0*(toposition.longitude-startpos.longitude) + startpos.longitude = startpos.longitude and when you interpolate with a 1 the formula equates to the ending position. 1*toposition.longitude - 1 * startpos.longitude + startpos.longitude = toposition.longitude. Good Luck with this. Try using the more deluxe acceloratedecelorateinterpolator. Good Luck.
  • AKASH WANGALWAR
    AKASH WANGALWAR over 6 years
    @TheDevMan did you found the solution