jasonflaherty
jasonflaherty

Reputation: 1944

Not able to update tilt after getting marker bounds Gmap V2

I am using this to get the bounds of markers on my map:

markerList.add(m);
        LatLngBounds.Builder builder = new LatLngBounds.Builder();
        for (Marker marker : markerList) {
            builder.include(marker.getPosition());
        }
        LatLngBounds bounds = builder.build();
        CameraUpdate updatecamera = CameraUpdateFactory.newLatLngBounds(bounds, 50);
        map.animateCamera(updatecamera);

After getting update, I would like to tilt the map to 30 degrees.

I have used this to tilt the camera in the past, but it is not working with the bounds feature:

CameraPosition cameraPosition = new CameraPosition.Builder()
                        .target(meLoc).zoom(6).bearing(0).tilt(30).build();
                map.animateCamera(CameraUpdateFactory
                        .newCameraPosition(cameraPosition));

How do I add this tilt after getting the bounds?

Thanks

Upvotes: 4

Views: 1542

Answers (3)

marius
marius

Reputation: 637

The key point is not having an animateCamera(..) followed by another animateCamera(..) without enough delay, as they overlap. So you should better use moveCamera(..) first and then animateCamera(..), or use some delay technique for the second animateCamera(..) such as new Handler().postDelayed(..).

Upvotes: 0

Jaydipsinh Zala
Jaydipsinh Zala

Reputation: 16798

In order to set GoogleMap Tilt and Bound all marker you need to use following code.

googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 75));
CameraPosition camPos = new CameraPosition.Builder(googleMap.getCameraPosition())
                              .target(bounds.getCenter())
                              .bearing(bearing).tilt(45).build();
googleMap.animateCamera(CameraUpdateFactory
                              .newCameraPosition(camPos));

Upvotes: 0

Sean Barbeau
Sean Barbeau

Reputation: 11756

As you say, the Android Maps API v2 doesn't currently directly support animating the camera with both bounds and tilt info.

One workaround is to use the following steps:

  1. Do the camera animation you want to perform with the bounds, but leave out the tilt
  2. Listen for the end of the above camera animation, get the current camera position, and then perform the tilt

This has the effect of moving the camera to the bounds while looking straight down (i.e., tilt = 0), and then tilting the camera in place. I've found that this works well in some use cases, and actually looks nice, but in others its kind of awkward. It may or may not work for your particular use case.

To implement this, let's assume you have a main class MapScreen.java where your map is implemented. You'll need change it to include the camera listener interface, a reference to the camera position, a reference to your activity, an initial tilt value you want to use (you can alternately set this at runtime), and a default camera padding:

public class MapScreen extends FragmentActivity implements GoogleMap.OnCameraChangeListener {
    ...
    private GoogleMap map;
    public static CameraPosition lastCameraPosition;
    public static MapScreen mapScreen;
    public static float CAMERA_INITIAL_TILT = 30.0f;
    public static int CAMERA_PADDING = 100;       
    ...
    public void onCreate(Bundle savedInstanceState) {
        ...
        mapScreen = this;
        ...
        //Set up map object here like normal
        map = ((SupportMapFragment)(getSupportFragmentManager().findFragmentById(R.id.map))).getMap();
        ...
        //Set camera change listener
        map.setOnCameraChangeListener(this);
    }
    ...
}

In this class, you'll also need to add a method to listen and save the location of the camera when the first animation stops:

@Override
public void onCameraChange(CameraPosition position) {
    //Save the last camera position so we can reference it when tilting the camera following animations
    lastCameraPosition = position;      
}

Also, add an inner class you can reference that performs the tilt after the first animation finishes (with a slight delay to get the correct CameraPosition):

public class tiltOnFinishAnimation implements CancelableCallback {

    @Override
    public void onCancel() {
        //Do nothing
    }

    @Override
    public void onFinish() {
        //We want to run the tilt animation, but the CameraPosition needed to center the camera in the right place
        //is only available after the onFinish() method completes.  So, we delay this by 10 ms to let the CameraPosition update
        final Handler handler = new Handler(); 
        handler.postDelayed(new Runnable() { 
          public void run() {
              mapScreen.runOnUiThread(new Runnable() {
                    public void run() {             
                        if(lastCameraPosition != null){
                            //Finish with a tilt
                            CameraPosition cameraPosition = new CameraPosition.Builder()
                                .target(lastCameraPosition.target)
                                .zoom(lastCameraPosition.zoom)                   
                                .bearing(lastCameraPosition.bearing)
                                .tilt(CAMERA_INITIAL_TILT)
                                .build();                   
                            //Perform the tilt!
                            mapScreen.map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));                             
                        }
                    }
                });
          } 
        }, 10);         
    }       
}

Finally, when you want to move the camera, execute your normal code, but first identify some of the map view attributes needed for animating the camera correctly based on orientation, and include a reference to the callback to execute when the first part of the animation without the tilt stops:

//Get the View height and width, so we don't exceed the screen size after padding for the camera updates
int width;
int height;
if(mapFragment != null){
    width = mapFragment.getView().getWidth();
    height = mapFragment.getView().getHeight();
}else{      
    //If the map fragment hasn't been instantiated yet, use the entire display
    if (android.os.Build.VERSION.SDK_INT >= 13){
        Display display = getWindowManager().getDefaultDisplay();
        Point size = new Point();
        display.getSize(size);
        width = size.x;
        height = size.y;
    }else{
        Display display = getWindowManager().getDefaultDisplay();
        width = display.getWidth();
        height = display.getHeight();
    }
}

if(getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE){               
    //Use verticle size for padding 
    CAMERA_PADDING = (int) (height * 0.2f);
}else{
    //Use horizontal size for padding
    CAMERA_PADDING = (int) (width * 0.2f);
}    

//Your code
markerList.add(m);
LatLngBounds.Builder builder = new LatLngBounds.Builder();
for (Marker marker : markerList) {
    builder.include(marker.getPosition());
}
LatLngBounds bounds = builder.build();

//Here's the new code below that triggers first the movement to the bounds, then the tilt (as a callback)
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, width, height, CAMERA_PADDING), new tiltOnFinishAnimation());

Upvotes: 3

Related Questions