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
}
}
});
Related
I would like to translate a view from pointA to pointB. imagine a line is drawn from pointA to pointB. the view should be translated to pointB along that invisible line. how a can i acheieve this. here is what i have tried so far:
getView().animate().translationX(deltaX)
getView().animate().translationY(deltaY)
but im not getting the results i want. to be specific i am using a google map and i want to move one marker to another location using translation.
I believe this repo will help you achieve your desired goal.
i am using a google map and i want to move one marker to another
location
I think the animateMarker() method in the MapUtils.java will help you achieve this,
public static void animateMarker(final Location destination, final Marker marker) {
if (marker != null) {
final LatLng startPosition = marker.getPosition();
final LatLng endPosition = new LatLng(destination.getLatitude(), destination.getLongitude());
final float startRotation = marker.getRotation();
final LatLngInterpolator latLngInterpolator = new LatLngInterpolator.LinearFixed();
ValueAnimator valueAnimator = ValueAnimator.ofFloat(0, 1);
valueAnimator.setDuration(1000); // duration 1 second
valueAnimator.setInterpolator(new LinearInterpolator());
valueAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
#Override public void onAnimationUpdate(ValueAnimator animation) {
try {
float v = animation.getAnimatedFraction();
LatLng newPosition = latLngInterpolator.interpolate(v, startPosition, endPosition);
marker.setPosition(newPosition);
marker.setRotation(computeRotation(v, startRotation, destination.getBearing()));
} catch (Exception ex) {
// I don't care atm..
}
}
});
valueAnimator.start();
}
}
I think your way must be more complex to achieve this goal.
Need to draw a transparent cover that must be clickable and focusable to receive touch events and prevent map changes from user input (for example, FrameLayout or custom View) above MapView. And then draw a "fake marker" on this Surface, animate, and finally destroy them.
The trick is next:
You have a marker at point A
Show Surface above all map to prevent touch
Draw new view "fake marker" on this Surface (above original marker)
Remove the original marker from the map
Animate/Translate your new marker to point B
Draw a new marker on the map at point B
Hide Surface with "fake marker"
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));
}
In our application, a lot of markers are drawn in different locations and in certain cases at a certain zoom level, markers overlap each other. So when I click on the marker, I expect the top marker's onMarkerClick to be fired but instead it is fired for the last hidden marker i-e the last marker, with no markers behind it.
What do you suggest I do? Also, I have no info windows, therefore I return true from onMarkerClick method.
I found the solution here: https://github.com/googlemaps/android-maps-utils/issues/26
mGoogleMap.setInfoWindowAdapter(new GoogleMap.InfoWindowAdapter()
{
#Override
public View getInfoWindow(Marker marker)
{
// Empty info window.
return new View(getApplicationContext());
}
#Override
public View getInfoContents(Marker marker)
{
return null;
}
});
Identify the size of your maker relative to the overall screen (e.g. 10%). Define this as a float called IMAGE_SIZE_RATIO
Maintain List markers as you add markers to your map. In your OnMarkerClickListener onMarkerClick method iterate through your other markers and compare distance between the markers relative to the current visible map dimensions and the marker size. As in the following example code:
static final float IMAGE_SIZE_RATIO = .15f; //define how big your marker is relative to the total screen
private void setupListeners() {
getMap().setOnMarkerClickListener(new GoogleMap.OnMarkerClickListener() {
#Override
public boolean onMarkerClick(Marker marker) {
LatLngBounds b = getMap().getProjection().getVisibleRegion().latLngBounds;
Float distance = distanceBetweenPoints(b.northeast, b.southwest) * IMAGE_SIZE_RATIO;
for (Marker m : makers ) {
if (marker.equals(m) ) { continue; } //don't compare the same one
if (distanceBetweenPoint(m.getPosition(), marker.getPosition()) {
/*Note do onMarkerClick this as an Aynch task and continue along
if also want to fire off against the main object.
*/
return onMarkerClick(m);
}
}
// do the operation you want on the actual marker.
}
....(remainder of listener)...
}
}
protected Float getDistanceInMeters(LatLng a, LatLng b) {
Location l1 = new Location("");
Location l2 = new Location("");
l1.setLatitude(a.latitude);
l1.setLongitude(a.longitude);
l2.setLatitude(b.latitude);
l2.setLongitude(b.longitude);
return l1.distanceTo(l2)
}
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.
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.