Google map camera position on multiple markers - android

I am using google map API 2 and showing multiple markers on it. My problem it that I want my camera to be positioned on all my markers.
I have done it for single marker as
myMap.moveCamera(CameraUpdateFactory.newLatLngZoom(MyLocation, 22));

I have Used Below Way to see all markers in view. It will Bound your Mapview including all the Lat-Long Location you have in your arraylist.
// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
final View mapView = getSupportFragmentManager().findFragmentById(R.id.map).getView();
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressLint("NewApi")
#Override
public void onGlobalLayout() {
LatLngBounds.Builder bld = new LatLngBounds.Builder();
for (int i = 0; i < YOUR_ARRAYLIST.size(); i++) {
LatLng ll = new LatLng(YOUR_ARRAYLIST.get(i).getPos().getLat(), YOUR_ARRAYLIST.get(i).getPos().getLon());
bld.include(ll);
}
LatLngBounds bounds = bld.build();
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 70));
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
}
});
}
Hope it Will Help.

Related

Make Google Maps Markers draggable within region/area?

I am creating markers based on my location and I would like to make the markers draggable within 1km of that location.
So, basically I want to know how to make a marker draggable within a certain area/region only and not the entire map.
Thank you
You have to define bounds and check if the new position is outside the bounds in the onDragListener of the marker: if the new position is outside the bounds you can reset the marker to the last valid position or do whatever you want.
To match if the marker is-or-not inside the bounds you must use the method contains of the LatLngBounds object.
Something like this:
LatLngBounds bounds;
LatLngBounds.Builder builder = new LatLngBounds.Builder();
// You construct your bounds in a way like this
builder.include(new LatLng(latitude1, longitude1));
builder.include(new LatLng(latitude2, longitude2));
builder.include(new LatLng(latitude3, longitude3));
// etc
bounds = builder.build();
googleMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
#Override
public void onMarkerDragStart(Marker marker) {
}
#Override
public void onMarkerDrag(Marker marker) {
}
#Override
public void onMarkerDragEnd(Marker marker) {
if (bounds.contains(marker.getPosition())) {
// cast your spell
} else {
// you can't drag here
}
}
});

Android Google Map show markers on zoom change

Guys I have to show markers on google maps with zoom.When user zoom in or zoom out markers will be visible covering the map area which is on the screen.How can I do this using Android google map?
Okay so you can use a CameraChangeListener:
private HashMap<Integer, Marker> courseMarkers = new HashMap<Integer, Marker>();
//all your visible markers
ArrayList<Item> yourMarkerList = new ArrayList<Item>();
//method to add all your markers with unique ids
addItemsToMap(); //first call to initially show the markers you want
googleMap.setOnCameraChangeListener(new OnCameraChangeListener() {
private float currentZoom = -1; //keep track of your current zoom level
#Override
public void onCameraChange(CameraPosition camera) {
if (camera.zoom != currentZoom){
currentZoom = camera.zoom;
//here you will then check your markers
addItemsToMap(yourMarkerList);
}
}
});
You will need a class Item that has a variable for a unique int id and a MarkerOptions
private void addItemsToMap(List<Item> items)
{
if(this.mMap != null)
{
//This is the current user-viewable region of the map
LatLngBounds bounds = this.mMap.getProjection().getVisibleRegion().latLngBounds;
//Loop through all the items that are available to be placed on the map
for(Item m : item)
{
//If the item is within the the bounds of the screen
if(bounds.contains(item.getMarker().getPosition()))
{
//If the item isn't already being displayed
if(!courseMarkers.containsKey(item.getId()))
{
//Add the Marker to the Map and keep track of it with the HashMap
//getMarkerForItem just returns a MarkerOptions object
this.courseMarkers.put(item.getId(), this.googleMap.addMarker(item.getMarker())); //getmarkerforitem
}
}
//If the marker is off screen
else
{
//If the course was previously on screen
if(courseMarkers.containsKey(item.getId()))
{
//1. Remove the Marker from the GoogleMap
courseMarkers.get(item.getId()).remove();
//2. Remove the reference to the Marker from the HashMap
courseMarkers.remove(item.getId());
}
}
}
}
}
This should do it
private void pointToPosition(LatLng position) {
//Build camera position
CameraPosition cameraPosition = new CameraPosition.Builder()
.target(position)
.zoom(15).build();
//Zoom in and animate the camera.
mGoogleMap.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
}

Waiting until the google map has size in a MapFragment

My activity contains a MapFragment in a LinearLayout. I do the following
in onCreate:
I inflate this layout using setContentView in the onCreate method of
my activity.
Get a handle to the GoogleMap using getMap().
in onStart:
I get some place coordinates from an SQLite Database
add corresponding markers to the map
add these points to a LatLngBounds.Builder
animate the camera using newLatLngBounds(Builder.build(), 10)
According to maps api reference, I shouldn't call newLatLngBounds(LatLngBounds bounds, int padding) before making sure that the map has a size. I indeed get an IllegalStateException at this point. But what is the right method for waiting until the map has a size?
The solution by rusmus didn't work for me. I used this one instead:
map.setOnMapLoadedCallback(new GoogleMap.OnMapLoadedCallback() {
#Override
public void onMapLoaded() {
map.animateCamera(cameraUpdate);
}
});
If you know the map size, you can avoid waiting and move the camera before the map is displayed. We finally used the display size as an approximation of the map size (but you could find out the exact size if you want to be more precise):
final DisplayMetrics display = getResources().getDisplayMetrics();
final int padding = display.widthPixels / 20;
final CameraUpdate cameraUpdate = CameraUpdateFactory.newLatLngBounds(
boundsBuilder.build(), display.widthPixels, display.heightPixels, padding);
map.moveCamera(cameraUpdate);
I have succesfully used the following code in the past:
final LatLngBounds.Builder builder = new LatLngBounds.Builder();
final View mapView = fragment.getView();
final GoogleMap map = fragment.getMap():
//Add points to builder. And get bounds...
final LatLngBounds bounds = builder.build();
// Pan to see all markers in view.
// Cannot zoom to bounds until the map has a size.
if (mapView.getViewTreeObserver().isAlive()) {
mapView.getViewTreeObserver().addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
public void onGlobalLayout() {
mapView.getViewTreeObserver().removeGlobalOnLayoutListener(this);
map.animateCamera(CameraUpdateFactory.newLatLngBounds(bounds, 50), 1500, null);
}
});
}
With the latest GoogleServices you can use MapFragment.getMapAsync.
Directly from the docs
Sets a callback object which will be triggered when the GoogleMap instance is ready to be used.

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
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:
Do the camera animation you want to perform with the bounds, but leave out the tilt
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());
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));
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(..).

Adjusting google map (api v2) zoom level in android

I'am using maps api v2 in my app. I have to show my current location and target location on the map such that both the locations are visible (at the greatest possible zoom level) on the screen. Here is what i have tried so far...
googleMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.mapFragment)).getMap();
if(googleMap != null){
googleMap.setMyLocationEnabled(true);
LatLng targetLocationLatLng = new LatLng(modelObject.getLattitude(), modelObject.getLongitude());
LatLng currentLocationLatLng = new LatLng(this.currentLocationLattitude, this.currentLocationLongitude);
googleMap.addMarker(new MarkerOptions().position(targetLocationLatLng).title(modelObject.getLocationName()).icon(BitmapDescriptorFactory.fromResource(R.drawable.location_icon)));
LatLngBounds bounds = new LatLngBounds(currentLocationLatLng, targetLocationLatLng);
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 3));
}
App is force closing due to the following :
java.lang.IllegalStateException: Map size should not be 0. Most likely, layout has not yet occured for the map view.
How can i get max possible zoom level? Please help me.
In my project I use the com.google.android.gms.maps.model.LatLngBounds.Builder
Adapted to your source code it should look something like this:
Builder boundsBuilder = new LatLngBounds.Builder();
boundsBuilder.include(currentLocationLatLng);
boundsBuilder.include(targetLocationLatLng);
// pan to see all markers on map:
LatLngBounds bounds = boundsBuilder.build();
googleMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds, 3));
A good method to avoid this problem is to use a ViewTreeObserver to the layout containing the map fragment and a listener, to ensure that the layout has first been initialised (and hasn't a width=0) using addOnGlobalLayoutListener, as below:
private void zoomMapToLatLngBounds(final LinearLayout layout,final GoogleMap mMap, final LatLngBounds bounds){
ViewTreeObserver vto = layout.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {
#SuppressWarnings("deprecation")
#Override
public void onGlobalLayout() {
layout.getViewTreeObserver().removeGlobalOnLayoutListener(this);
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(bounds,OVERVIEW_MAP_PADDING));
}
});
}

Categories

Resources