How to change Info-window (custom) Position in google map v2 android? - android

I have a screen with google map, on top of screen there is one AutotextView for search place, and make a custom info window to show more details, problem is when user click on any mark custom window popup as their default behaviour (center on screen), so it mixed up autotextview, Can I change info-window position on screen, i.e bottom or anything like that.

If you want to adjust Marker location perfect center on google map screen with popup then please use below code in that i have get popup height and based on that update y axis.i hope it will help you.
public boolean onMarkerClick(Marker marker) {
//Please use fix height popup
float container_height = getResources().getDimension(R.dimen.DIP_300);
Projection projection = mGoogleMap.getProjection();
Point markerScreenPosition = projection.toScreenLocation(marker.getPosition());
Point pointHalfScreenAbove = new Point(markerScreenPosition.x,(int) (markerScreenPosition.y - (container_height / 2)));
LatLng aboveMarkerLatLng = projection.fromScreenLocation(pointHalfScreenAbove);
marker.showInfoWindow();
CameraUpdate center = CameraUpdateFactory.newLatLng(aboveMarkerLatLng);
mGoogleMap.moveCamera(center);
mGoogleMap.animateCamera(center);
marker.showInfoWindow();
return true;
}

Currently you cannot change the info window to be below marker. This is already requested and discussed on gmaps-api-issues.
I can only suggest you to animate marker after being clicked to a different position. Add OnMarkerClickListener and return true (handled) there. After that you can call:
marker.showInfoWindow();
map.animateCamera(...);
to create an effect similar to default but with a different position.

Google Map Info Window Position always on top middle of marker now. If marker is rotated.
double angle = MARKER_ROTATION_ANGLE;
double x = Math.sin(-angle * Math.PI / 180) * 0.5 + 0.5;
double y = -(Math.cos(-angle * Math.PI / 180) * 0.5 - 0.5);
marker.setInfoWindowAnchor((float)x, (float)y);
Explanation:
instead of MARKER_ROTATION_ANGLE you have to give the exact rotation of your marker. Then it will be work fine. :)

Related

Manually add a floorplan to Google Maps with Android Studio

I have a google maps app that I need to be able to upload different floorplans to. So far I am adding the floorplan image to the map using a ground overlay object like this:
LatLngBounds bounds = new LatLngBounds(new LatLng(floorplan.get_swlat(), floorplan.get_swlng()),
new LatLng(floorplan.get_nelat(), floorplan.get_nelng()));
GroundOverlayOptions overlayOptions = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(floorplan.get_floorplanimage())).positionFromBounds(bounds);
mMap.addGroundOverlay(overlayOptions);
This adds the floorplan to the map, but the problem is that it is only north-south facing, so it won't work for buildings that don't perfectly sit like that. So I was wondering if there was a way to go in and manually place it (and use fingers to rotate and scale the image) where I need it to be. Anyone know where to even begin?
Took some time but I finally figured something out. Instead of adding the overlay using the two corners I use the center lat/lon and the width and height. I add the overlay as follows.
mOverlayOptions = new GroundOverlayOptions()
.image(BitmapDescriptorFactory.fromBitmap(floorplan.get_floorplanimage()))
.position(new LatLng(floorplan.get_clat(), floorplan.get_clng()), (float) floorplan.get_width(), (float) floorplan.get_height())
.bearing((float) floorplan.get_bearing())
.transparency(mOpacity);
mOverlay = mMap.addGroundOverlay(mOverlayOptions);
So you have to give the floorplan initial values to begin.Then I added two markers, one located at the center of the overlay (same lat/lon) and another one located along the center of the right edge of the overlay (mSizeMarker). Make sure they're draggable. I had to do some math to figure out where to place the one on the right edge.
mCenterMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(floorplan.get_clat(), floorplan.get_clng())));
Double new_longitude = floorplan.get_clng() + (floorplan.get_width() / 2 / (6371000)) * (180 / 3.14159265) / Math.cos(floorplan.get_clat() * 3.14159265/180);
mSizeMarker = mMap.addMarker(new MarkerOptions().position(new LatLng(floorplan.get_clat(), new_longitude)));
mCenterMarker.setDraggable(true);
mSizeMarker.setDraggable(true);
All that's left is to add an OnMarkerDragListener:
mMap.setOnMarkerDragListener(new GoogleMap.OnMarkerDragListener() {
#Override
public void onMarkerDragStart(Marker marker) {
}
}
#Override
public void onMarkerDrag(Marker marker) {
if (marker.equals(mCenterMarker)) {
mOverlay.remove();
mOverlayOptions.position(marker.getPosition(), mOverlay.getWidth(), mOverlay.getHeight());
mOverlay = mMap.addGroundOverlay(mOverlayOptions);
mSizeMarker.setPosition(new LatLng(marker.getPosition().latitude, marker.getPosition().longitude + (mOverlay.getWidth() / 2 / (6371000)) * (180 / 3.14159265) / Math.cos(marker.getPosition().latitude * 3.14159265/180)));
}
if (marker.equals(mSizeMarker)) {
marker.setPosition(new LatLng(mCenterMarker.getPosition().latitude, marker.getPosition().longitude));
double newWidth = ((marker.getPosition().longitude - mCenterMarker.getPosition().longitude) / ((180 / 3.14159265) / Math.cos(mCenterMarker.getPosition().latitude * 3.14159265/180))) * 6371000 * 2;
mOverlay.remove();
mOverlayOptions.position(mCenterMarker.getPosition(), (float) newWidth);
mOverlay = mMap.addGroundOverlay(mOverlayOptions);
}
}
#Override
public void onMarkerDragEnd(Marker marker) {
if (marker.equals(mSizeMarker)) {
marker.setPosition(new LatLng(mCenterMarker.getPosition().latitude, marker.getPosition().longitude));
}
}
});
Use the middle marker to drag where you want the floorplan to be located, and the one on the right to change the width (the height will automatically update correspondingly).
Then when the image is positioned correctly, just have a save button somewhere that updates where the floorplan is stored with the position, width, and height of mOverlay. It would be possible to add another marker to manually adjust the bearing, but that's more math than I need to do right now. I'll just keep adjusting it when I set it originally. Hope this helps anyone else who comes along this problem, I know this solution is working great for me so far.

How to focus on location on Google maps, considering a view is on top of it?

Background
Suppose I have a Google maps view, and another view on top of it, that covers a part of it, hiding some content of the map.
The problem
I need to make the "camera" of the map, to focus and have a marker on a coordinate , yet let it all be in the middle of the visible part of the map.
Something like this:
The original code was focusing on (about) the center of the entire screen, making the marker almost invisible (as the bottom view covers it).
Thing is, I can't find the proper way to set the correct value to the Y coordinate of the map itself (meaning latitude).
What I've tried
I tried, given the height of the bottom view, and the coordinate that I've put the marker on, to calculate the delta (yet of course not change the marker itself) :
final float neededZoom = 6.5f;
int bottomViewHeight = bottomView.getHeight();
LatLng posToFocusOn = ...;
final Point point = mMap.getProjection().toScreenLocation(posToFocusOn);
final float curZoom = mMap.getCameraPosition().zoom;
point.y += bottomViewHeight * curZoom / neededZoom;
posToFocusOn = mMap.getProjection().fromScreenLocation(point);
final CameraUpdate cameraPosition = CameraUpdateFactory.newCameraPosition(new Builder().target(posToFocusOn).zoom(neededZoom).build());
Sadly, this focuses way above the marker.
The question
What's wrong with what I wrote? What can I do to fix it?
ok, I've found a workaround, which I think works on all devices (tested on 3, each with a different screen resolution and size) :
I've measured how many pixels (and then converted to DP) a change of one degree has on the marker itself.
From this, I measured the height of each view, and calculated the delta needed to move the camera.
In my case, it's this way (supposing the zoom is 6.5f) :
//measured as 223 pixels on Nexus 5, which has xxhdpi, so divide by 3
final float oneDegreeInPixels = convertDpToPixels( 223.0f / 3.0f);
final float mapViewCenter = mapViewHeight / 2.0f;
final float bottomViewHeight = ...;
final float posToFocusInPixelsFromTop = (mapViewHeight - bottomViewHeight) / 2.0f ;// can optionally add the height of the view on the top area
final float deltaLatDegreesToMove = (mapViewCenter - posToFocusInPixelsFromTop) / oneDegreeInPixels;
LatLng posToFocusOn = new LatLng(latitude - deltaLatDegreesToMove, longitude);
final CameraUpdate cameraPosition = CameraUpdateFactory.newCameraPosition(new Builder().target(posToFocusOn).zoom(neededZoom).build());
And it worked.
I wonder if it can be adjusted to support any value of zoom.
Your code is almost right, but it goes above the marker because you are taking into account bottomViewHeight when computing point.y instead of bottomViewHeight/2 (When your view's size is 200px, you only need to displace the map 100px to recenter it):
point.y += (bottomViewHeight / 2) * curZoom / neededZoom;
Update:
This is a more general approach taht takes into account the map bounds and calculates a new map bounds according to the height of your bottomView. This is zoom independent.
public void recenter() {
LatLngBounds mapBounds = mMap.getProjection().getVisibleRegion().latLngBounds;
Point nothEastPoint = mMap.getProjection().toScreenLocation(mapBounds.northeast);
Point souhWestPoint = mMap.getProjection().toScreenLocation(mapBounds.southwest);
Point newNorthEast = new Point(nothEastPoint.x, nothEastPoint.y + bottomView.getHeight() / 2);
Point newSouhWestPoint = new Point(souhWestPoint.x, souhWestPoint.y + bottomView.getHeight() / 2);
LatLngBounds newBounds = LatLngBounds.builder()
.include(mMap.getProjection().fromScreenLocation(newNorthEast))
.include(mMap.getProjection().fromScreenLocation(newSouhWestPoint))
.build();
mMap.moveCamera(CameraUpdateFactory.newLatLngBounds(newBounds, 0));
}
Note that each time you call recenter() the map will move.

Map marker position with animateCamera to screen location x, y

Dears,
I have a map view that covers the whole screen. On the top of it, there is a view pager.
The view pager consist of two parts, top 40% and bottom 60%, the top one is just a transparent view.
While swiping the view pager, marker displayed on map should be located to middle of transparent top view 40%.
This image describe the story:
How to achieve this?
I tried this, but with no luck:
public void FollowVehicle(clsFollowMode vehicle){
final LatLng vehiclePosition = new LatLng(vehicle.getLatitude(), vehicle.getLongtitude());
Marker vehicleMarker = myGMap.addMarker(new MarkerOptions()
.position(vehiclePosition)
.title(vehicle.getDeviceName())
.snippet(String.valueOf(vehicle.getSpeed()))
.icon(BitmapDescriptorFactory.fromResource(R.drawable.ic_vehicle_follow)));
float zoom_lvl = myGMap.getCameraPosition().zoom;
double dpPerdegree = 256.0*Math.pow(2, zoom_lvl)/170.0;
double screen_height = (double) mapContainer.getHeight();
double screen_height_30p = -20.0*screen_height/100.0;
double degree_30p = screen_height_30p/dpPerdegree;
LatLng centerlatlng = new LatLng( vehiclePosition.latitude + degree_30p, vehiclePosition.longitude );
myGMap.animateCamera( CameraUpdateFactory.newLatLngZoom( centerlatlng, 15 ), 1000, null);
}
Any help? the above solution found here.
Regards,
If I understood you correctly, then your problem is the fact that you placed the map as full screen fragmnet, and on top of this you placed the ViewPager. as a result when you center on the marker the map does that but the marker is under the ViewPager.
You can trick the map into thinking that it has a smaller size then it really is, by using the GoogleMap.setPadding method, you can read more about it here:
https://developers.google.com/maps/documentation/android/map#map_padding

How to center the camera so that marker is at the bottom of screen? (Google map api V2 Android)

When a marker is clicked, the default behavior for the camera is to center it on screen, but because I usually have long text description in the info window, it's more convenient to actually change the camera position so that the marker is on the bottom of screen(making the info window in the center of screen). I think I should be able to do that by overriding onMarkerClick function like below (the default behavior is cancelled when this function return true)
#Override
public boolean onMarkerClick(final Marker marker) {
// Google sample code comment : We return false to indicate that we have not
// consumed the event and that we wish
// for the default behavior to occur (which is for the camera to move
// such that the
// marker is centered and for the marker's info window to open, if it
// has one).
marker.showInfoWindow();
CameraUpdate center=
CameraUpdateFactory.newLatLng(new LatLng(XXXX,
XXXX));
mMap.moveCamera(center);//my question is how to get this center
// return false;
return true;
}
Edit:
Problem solved using accepted answer's steps, codes below:
#Override
public boolean onMarkerClick(final Marker marker) {
//get the map container height
LinearLayout mapContainer = (LinearLayout) findViewById(R.id.map_container);
container_height = mapContainer.getHeight();
Projection projection = mMap.getProjection();
LatLng markerLatLng = new LatLng(marker.getPosition().latitude,
marker.getPosition().longitude);
Point markerScreenPosition = projection.toScreenLocation(markerLatLng);
Point pointHalfScreenAbove = new Point(markerScreenPosition.x,
markerScreenPosition.y - (container_height / 2));
LatLng aboveMarkerLatLng = projection
.fromScreenLocation(pointHalfScreenAbove);
marker.showInfoWindow();
CameraUpdate center = CameraUpdateFactory.newLatLng(aboveMarkerLatLng);
mMap.moveCamera(center);
return true;
}
Thanks for helping ^ ^
I might edit this answer later to provide some code, but what I think could work is this:
Get LatLng (LatLng M) of the clicked marker.
Convert LatLng M to a Point (Point M) using the Projection.toScreenLocation(LatLng) method. This gives you the location of the marker on the device's display (in pixels).
Compute the location of a point (New Point) that's above Point M by half of the map's height.
Convert the New Point back to LatLng and center the map on it.
Look here for my answer on how to get the map's height.
// googleMap is a GoogleMap object
// view is a View object containing the inflated map
// marker is a Marker object
Projection projection = googleMap.getProjection();
LatLng markerPosition = marker.getPosition();
Point markerPoint = projection.toScreenLocation(markerPosition);
Point targetPoint = new Point(markerPoint.x, markerPoint.y - view.getHeight() / 2);
LatLng targetPosition = projection.fromScreenLocation(targetPoint);
googleMap.animateCamera(CameraUpdateFactory.newLatLng(targetPosition), 1000, null);
I prefer Larry McKenzie's answer which it doesn't depend on screen projection (i.e. mProjection.toScreenLocation()), my guess is the projection resolution will go poor when the map zoom level is low, it made me sometimes couldn't get an accurate position. So, calculation based on google map spec will definitely solve the problem.
Below is an example code of moving the marker to 30% of the screen size from bottom.
zoom_lvl = mMap.getCameraPosition().zoom;
double dpPerdegree = 256.0*Math.pow(2, zoom_lvl)/170.0;
double screen_height = (double) mapContainer.getHeight();
double screen_height_30p = 30.0*screen_height/100.0;
double degree_30p = screen_height_30p/dpPerdegree;
LatLng centerlatlng = new LatLng( latlng.latitude + degree_30p, latlng.longitude );
mMap.animateCamera( CameraUpdateFactory.newLatLngZoom( centerlatlng, 15 ), 1000, null);
If you don't care about the map zooming in and just want the marker to be at the bottom see below, I think it's a simpler solution
double center = mMap.getCameraPosition().target.latitude;
double southMap = mMap.getProjection().getVisibleRegion().latLngBounds.southwest.latitude;
double diff = (center - southMap);
double newLat = marker.getPosition().latitude + diff;
CameraUpdate centerCam = CameraUpdateFactory.newLatLng(new LatLng(newLat, marker.getPosition().longitude));
mMap.animateCamera(centerCam);
I had the same issue, I tried the following perfectly working solution
mMap.setOnMarkerClickListener(new OnMarkerClickListener()
{
#Override
public boolean onMarkerClick(Marker marker)
{
int yMatrix = 200, xMatrix =40;
DisplayMetrics metrics1 = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metrics1);
switch(metrics1.densityDpi)
{
case DisplayMetrics.DENSITY_LOW:
yMatrix = 80;
xMatrix = 20;
break;
case DisplayMetrics.DENSITY_MEDIUM:
yMatrix = 100;
xMatrix = 25;
break;
case DisplayMetrics.DENSITY_HIGH:
yMatrix = 150;
xMatrix = 30;
break;
case DisplayMetrics.DENSITY_XHIGH:
yMatrix = 200;
xMatrix = 40;
break;
case DisplayMetrics.DENSITY_XXHIGH:
yMatrix = 200;
xMatrix = 50;
break;
}
Projection projection = mMap.getProjection();
LatLng latLng = marker.getPosition();
Point point = projection.toScreenLocation(latLng);
Point point2 = new Point(point.x+xMatrix,point.y-yMatrix);
LatLng point3 = projection.fromScreenLocation(point2);
CameraUpdate zoom1 = CameraUpdateFactory.newLatLng(point3);
mMap.animateCamera(zoom1);
marker.showInfoWindow();
return true;
}
});
I also faced this problem and fixed it in a hacky way. Let's declare a double field first. You need to adjust the value of it based on your requirement but I recommend you keep it between 0.001~0.009 otherwise you can miss your marker after the zoom animation.
double offset = 0.009
/*You can change it based on your requirement.
For left-right alignment please kindly keep it between 0.001~0.005 */
For bottom-centered:
LatLng camera = new LatLng(marker.getPosition().latitude+offset , marker.getPosition().longitude);
//Here "marker" is your target market on which you want to focus
For top-centered:
LatLng camera = new LatLng(marker.getPosition().latitude-offset , marker.getPosition().longitude);
For left-centered:
LatLng camera = new LatLng(marker.getPosition().latitude, marker.getPosition().longitude+offset);
For right-centered:
LatLng camera = new LatLng(marker.getPosition().latitude-offset , marker.getPosition().longitude-offset);
Then finally call the -
mMap.animateCamera(CameraUpdateFactory.newLatLngZoom(camera, yourZoom));
I did a little research and according to the documentation the map is square and at zero zoom level the width and height is 256dp and +/- 85 degrees N/S. The map width increases with zoom level so that width and height = 256 * 2N dp. Where N is the zoom level. So in theory you can determine the new location by getting the map height and dividing it by 170 total degrees to get dp per degree. Then get the screen height (or mapview height) in dp divided it by two and convert half view size to degrees of latitude. Then set your new Camera point that many degrees of latitude south. I can add code if you need it but I'm on a phone at the moment.
I have been trying out all the solutions proposed here, and came with a combined implementation of them. Considering, map projection, tilt, zoom and info window height.
It doesn't really place the marker at the bottom of the "camera view", but I think it accommodates the info window and the marker centre pretty well in most cases.
#Override
public boolean onMarkerClick(Marker marker) {
mIsMarkerClick = true;
mHandler.removeCallbacks(mUpdateTimeTask);
mLoadTask.cancel(true);
getActivity().setProgressBarIndeterminateVisibility(false);
marker.showInfoWindow();
Projection projection = getMap().getProjection();
Point marketCenter = projection.toScreenLocation(marker.getPosition());
float tiltFactor = (90 - getMap().getCameraPosition().tilt) / 90;
marketCenter.y -= mInfoWindowAdapter.getInfoWindowHeight() / 2 * tiltFactor;
LatLng fixLatLng = projection.fromScreenLocation(marketCenter);
mMap.animateCamera(CameraUpdateFactory.newLatLng(fixLatLng), null);
return true;
}
And then, your custom adapter would have to keep an instance of the info window inflated view, to be able to fetch its height.
public int getInfoWindowHeight(){
if (mLastInfoWindoView != null){
return mLastInfoWindoView.getMeasuredHeight();
}
return 0;
}
Anyone who's still looking to center the camera according to location coordinates
CameraPosition cameraPosition = new CameraPosition.Builder().target(new LatLng(Lat, Lon))
.zoom(15)
.bearing(0)
.tilt(45)
.build();
map.animateCamera(CameraUpdateFactory.newCameraPosition(cameraPosition));
Credits
After some experiences i've implemented the solution that fine for me.
DisplayMetrics metrics = new DisplayMetrics();
context.getWindowManager().getDefaultDisplay().getMetrics(metrics);
Point targetPoint = new Point(metrics.widthPixels / 2, metrics.heightPixels - metrics.heightPixels / 9);
LatLng targetLatlng = map.getProjection().fromScreenLocation(targetPoint);
double fromCenterToTarget = SphericalUtil.computeDistanceBetween(map.getCameraPosition().target, targetLatlng);
LatLng center = SphericalUtil.computeOffset(new LatLng(location.latitude, location.longitude), fromCenterToTarget/1.2, location.bearing);
CameraUpdate camera = CameraUpdateFactory.newLatLng(center);
map.animateCamera(camera, 1000, null);
Here. First, we pick the physical point on the screen where the marker should be moved. Then, convert it to LatLng. Next step - calculate distance from current marker position (in center) to target. Finally, we move the center of map straight from the marker to calculated distance.
I needed something similar, but with also zoom, tilt and bearing in the equation.
My problem is more complex, but the solution is a sort of generalization so it could be applied also to the problem in the question.
In my case, I update programmatically the position of a marker; the camera can be rotated, zoomed and tilted, but I want the marker always visible at a specific percentage of the View height from the bottom. (similar to the car marker position in the Maps navigation)
The solution:
I first pick the map location on the center of the screen and the location of a point that would be visible at a percentage of the View from the bottom (using map projection); I get the distance between these two points in meters, then I calculate a position, starting from the marker position, moving for the calculated distance towards the bearing direction; this new position is my new Camera target.
The code (Kotlin):
val movePointBearing =
if (PERCENTAGE_FROM_BOTTOM > 50) {
(newBearing + 180) % 360
} else newBearing
val newCameraTarget = movePoint(
markerPosition,
distanceFromMapCenter(PERCENTAGE_FROM_BOTTOM),
markerBearing)
with the movePoint method copied from here:
https://stackoverflow.com/a/43225262/2478422
and the distanceFromMapCenter method defined as:
fun distanceFromMapCenter(screenPercentage: Int): Float {
val screenHeight = mapFragment.requireView().height
val screenWith = mapFragment.requireView().width
val projection = mMap.projection
val center = mMap.cameraPosition.target
val offsetPointY = screenHeight - (screenHeight * screenPercentage / 100)
val offsetPointLocation = projection.fromScreenLocation(Point(screenWith / 2, offsetPointY))
return distanceInMeters(center, offsetPointLocation)
}
then just define a distanceInMeters method (for example using android Location class)
I hope the idea is clear without any further explanations.
One obvious limitation: it applies the logic using the current zoom and tilt, so it would not work if the new camera position requires also a different zoom_level and tilt.

Restricting the area the user can go to on Mapview

I am using a customised version of the mapview (OSMDroid version).
I am using custom tiles within it and I only want the user to be able to view the area where I have my custom tiles.
Is there a way to set the boundary lat longs so when they pan the map it doesn't go past these boundaries?
Update: I know this is an old question, but osmdroid now has a setScrollableAreaLimit() method that will achieve what you are looking for. There is also a setMinZoomLevel() and setMaxZoomLevel() method to easily restrict zoom levels.
Original answer:
Please keep an eye on:
http://code.google.com/p/osmdroid/issues/detail?id=209
A patch has already been created, and will likely be integrated shortly.
This is cross-posted from the osmdroid thread. There's now lists a BoundedMapView class, which implements the afortementioned patch.
For those of use using the .jar or otherwise not that familiar with
patches, I cobbled together a subclass of MapView that supports
limiting the user's view to a specific area.
Details on how to use it,
if not obvious, can be found at
http://www.sieswerda.net/2012/08/15/boundedmapview-a-mapview-with-limits/
Incase it helps anyone....
I have sort of a solution that I am using, it works ok, but could definitely be better as the map can go abit too far off the screen before it jumps back!
It uses the lat longs and works out where the map is, I set 4 coordinates which are roughly the 4 corners of the map I have found it works better if you set them slightly into the map rather exactly the corners, I then work out if the lat longs have left the screen completely.. if so it will bounce it halfway back:
I overrode the mapview and the OnTouch event of the map
#Override
public boolean onTouchEvent(MotionEvent ev) {
if (ev.getAction() == MotionEvent.ACTION_UP) {
// (only works for north of equator)
// * map right side (lat) can't go past the left (lat) of screen
// get geopoints of the 4 corners of the screen
Projection proj = getProjection();
GeoPoint screenTopLeft = proj.fromPixels(0, 0);
GeoPoint screenTopRight = proj.fromPixels(getWidth(), 0);
GeoPoint screenBottomLeft = proj.fromPixels(0, getHeight());
double screenTopLat = screenTopLeft.getLatitudeE6() / 1E6;
double screenBottomLat = screenBottomLeft.getLatitudeE6() / 1E6;
double screenLeftlong = screenTopLeft.getLongitudeE6() / 1E6;
double screenRightlong = screenTopRight.getLongitudeE6() / 1E6;
double mapTopLat = BoundsTopLeftCorner.getLatitudeE6() / 1E6;
double mapBottomLat = BoundsBottomLeftCorner.getLatitudeE6() / 1E6;
double mapLeftlong = BoundsTopLeftCorner.getLongitudeE6() / 1E6;
double mapRightlong = BoundsTopRightCorner.getLongitudeE6() / 1E6;
// screen bottom greater than map top
// screen top less than map bottom
// screen right less than map left
// screen left greater than map right
boolean movedLeft = false;
boolean movedRight = false;
boolean movedUp = false;
boolean movedDown = false;
boolean offscreen = false;
if (screenBottomLat > mapTopLat) {
movedUp = true;
offscreen = true;
}
if (screenTopLat < mapBottomLat) {
movedDown = true;
offscreen = true;
}
if (screenRightlong < mapLeftlong) {
movedLeft = true;
offscreen = true;
}
if (screenLeftlong > mapRightlong) {
movedRight = true;
offscreen = true;
}
if (offscreen) {
// work out on which plane it's been moved off screen (lat/lng)
if (movedLeft || movedRight) {
double newBottomLat = screenBottomLat;
double newTopLat = screenTopLat;
double centralLat = newBottomLat
+ ((newTopLat - newBottomLat) / 2);
if (movedRight)
this.getController().setCenter(
new GeoPoint(centralLat, mapRightlong));
else
this.getController().setCenter(
new GeoPoint(centralLat, mapLeftlong));
}
if (movedUp || movedDown) {
// longs will all remain the same
double newLeftLong = screenLeftlong;
double newRightLong = screenRightlong;
double centralLong = (newRightLong + newLeftLong) / 2;
if (movedUp)
this.getController().setCenter(
new GeoPoint(mapTopLat, centralLong));
else
this.getController().setCenter(
new GeoPoint(mapBottomLat, centralLong));
}
}
}
return super.onTouchEvent(ev);
}}
A few things I should point out if you are considering using this:
I make no guarentees that it will work for your situation and you should only use it as a starting point.
It will only work for areas north of the equator (I think) due to the way I've done the coords!
It works on the "action up" of the touch event, so it takes the point where the user takes their finger off the screen. This means when the map flings it's completely inaccurate as I could not work out where the map stopped, because of this I turned off the fling by overriding the fling event and not doing anything in it.. this does make the map a bit jolty!
If anyone has any better solutions or can improve my code please feel free!
I'm looking for exactly the same thing.
My best lead is to add an Overlay, which extends boolean onScroll(...). If this returns true, then the scroll is cancelled.
This is exactly how I want it, except for one thing: flinging/flicking. The same approach can be used to cancel fling events, though you only get to hear about it at the start of the fling.
Ideally, you'd be able to listen to the computeScroll() method, and limit the (x, y) of the scroll, based on mScroller.getCurX() and mScroller.getCurY().

Categories

Resources