I have the following functionality working in my app.
I Use MyLocationOverlay to get my current location.
I extended MyLocationOverlay in order to be able to drop a custom marker instead of the blinking blue marker.
I need help on the last requirement. I simply want a marker to stay fixed on the location that MyLocationOverlay says it found originally and not move around as it jumps from satellite to satellite.
What are my options for creating this type of user experience?
I would recommend saving off the first geopoint that gets fed into the drawMyLocation function inside the CustomLocationOverlay and using that instead of the myLocation fed to the function.
int intFirstGeoPoint = 0;
GeoPoint FirstGeoPoint;
protected void drawMyLocation(Canvas canvas, MapView mapView, Location lastFix, GeoPoint myLocation, long when) {
if(intFirstGeoPoint == 0){
FirstGeoPoint=myLocation;
intFirstGeoPoint=1;
}else{
myLocation=FirstGeoPoint;
}
// translate the GeoPoint to screen pixels
Point screenPts = mapView.getProjection().toPixels(myLocation, null);
...
...
You could also capture this location and create a new DrawableMapOverlay that only draws this point instead of hijacking the LocationOverlay
Related
I am using the indoor positioning framework wifislam and have a programming question.
So far I have given a MapView by the indoorLocationView of WifiSLAM. I'm working with the following code.
final IndoorLocationManager.Configuration config = new IndoorLocationManager.Configuration();
indoorLocationManager = new IndoorLocationManager(this, config,
onServiceConnected, LOCATION_CHOICE);
indoorLocationView = indoorLocationManager.createLocationView(this,
GOOGLE_MAPS_API_KEY);
final View mapContainer = findViewById(R.id.mapcontainer);
((ViewGroup) mapContainer).addView(indoorLocationView.getView());
MapView mapView = indoorLocationView.getGoogleMapView();
List<Overlay> mapOverlays = mapView.getOverlays();
Drawable drawable = this.getResources().getDrawable(R.drawable.pinred);
itemizedOverlay = new AddItemizedOverlay(drawable, mapView.getContext(), sm);
mapOverlays.add(itemizedOverlay);
and the AddItemizedOverlay has following methods:
#Override
public boolean onTap(GeoPoint geopoint, MapView mapView) {
mapOverlays.clear();
// geopoint = mapView.getProjection().fromPixels((int) event.getX(),
// (int) event.getY());
// latitude
if (geopoint != null) {
this.geopoint = geopoint;
lat = geopoint.getLatitudeE6();
// longitude
lon = geopoint.getLongitudeE6();
OverlayItem overlayitem = new OverlayItem(geopoint,
"Task Position", "Derzeitige Position vom Task");
this.addOverlay(overlayitem);
}
return false;
}
My problem is now, that the onTap method does not respond or react on touching on the device. As well the onTouch event has no reaction. I think those layers above of wifislam are preventing that I can reach the MapView. Is there any possibility to reach the MapView so I can add some markers on the map?
The reason for this is that there is a transparent view on top of the Google Maps view that is showing the floorplan. Try adding a listener on the view returned by IndoorLocationView#getView, but that may screw up the pinch-zoom/panning controls; you should double-check the effect (you probably want to return false from your listener unless one of your markers has been tapped).
If that doesn't work, your best bet is to contact WiFiSLAM support with your use case so they can update their SDK to meet your needs. Looks like there's a support email address in the FAQ topic of the help section of the SDK website.
I'm trying to develop a layout that shows a Google Map with a route drawn on a Overlay layer associated with this map. I want this mapView to be a small static map that shows, as a thumbnail, the main route the user followed, and then if the user clicks on it, an intent takes you to a different activity displaying the map in full screen with the route and all the zoom functionalities.
The thing is that although I override the onTap method of the Overlay setting there the intent to the new activity, it only works if I set the MapView as setEnabled(true), but if I do so, then the thumbnail map can be dragged and moved by the user.
I'm sorry if it is not clear enough, but I don't know how to explain it better.
Thanks in advance
This is my customized class which extends Overlay and overrides the onTap method:
class MapOverlay extends Overlay {
#Override
public boolean onTap(GeoPoint p, MapView mapView) {
Intent i = new Intent(getApplicationContext(),
RouteMapActivity.class);
startActivity(i);
return false;
};
And this is my onCreate method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.detailrun_activity);
map = (MapView) findViewById(R.id.mvMain);
map.setEnabled(true);
map.setClickable(true);
MapOverlay mapOverlay = new MapOverlay();
List<Overlay> listOfOverlays = map.getOverlays();
projection = map.getProjection();
listOfOverlays.clear();
listOfOverlays.add(mapOverlay);
double lat = 28.063119 * 1E6, longi = -82.41128 * 1E6;
GeoPoint point = new GeoPoint((int) lat, (int) longi);
MapController myMapController = map.getController();
myMapController.setCenter(point);
}
For now I'm only drawing a straight line between two GeoPoints, and I don't get any logcat errors.
The map with the route is indeed drawn, and the overrided onTap method works, but it seems it only recognizes the tap if my mapView is defined as enabled and clickable, but if I do so, then the user can also move and drag the map as long as he holds pressing the screen.
you can get static google map image as per your location by this link. that you can display in imageview and click on that you can target new activity which have MapView.. i think it may be a good option for you.
I'm curently using a class which extends from the Drawable on OsmDroid.
And on this class I draw a geometric form for each car I receive from internet.
I would like to add a listener on each car in order to give some informations when we touch the car.
With a OverlayItem we can do this :
ArrayList<OverlayItem> items = new ArrayList<OverlayItem>();
carOverlay.draw(new Canvas());
overlayItem = new OverlayItem("test", ""+i, geoPoint);
overlayItem.setMarker(carOverlay.getCurrent());
items.add(overlayItem);
ItemizedOverlay<OverlayItem> overlay = new ItemizedOverlayWithFocus<OverlayItem>(this.getApplicationContext(), items,
new ItemizedIconOverlay.OnItemGestureListener<OverlayItem>() {
#Override
public boolean onItemSingleTapUp(final int index, final OverlayItem item) {
Log.i("Touch","you just tap the car");
return true;
}
#Override
public boolean onItemLongPress(final int index, final OverlayItem item) {
return false;
}
});
With this piece of code, I can see the image I've just drawn, but no event when I touch a car, and if I remove the line :
overlayItem.setMarker(carOverlay.getCurrent());
to let the default marker being displayed instead of my custom marker, the touch events occure.
So what am I doing wrong ? must be the same no ?
This is not a 'proper' answer but as I am facing similar problem I resorted to using BOTH default draw and custom at the same time.
I just call super() at the end of my custom draw method on ItemizedIconOverlay and both my drawing and 'default' item marker are drawn.
Maybe it would be possible to tweak default marker to make it invisible (empty bitmap)... experiment. :)
#Override
public void draw(Canvas canvas, MapView mv, boolean shadow) {
if(!shadow) {
//my draw code
}
super.draw(canvas, mv, shadow);
}
tmouse is correct. If you're overriding the ItemizedOverlayWithFocus.draw() method to draw your car with canvas, you'll need to add:
super.draw(canvas, view, shadow);
The super will setup and use the OverlayItem's Hotspot which is (from what I can see in the source) used as the touchable area for gestures.
However you'll still see the original Markers AND your canvas drawn ones. PLUS if you move your cars, the touchable area won't move with it. (the Hotspot will not be for the new location you drew at)
There are only 2 real solutions.
1) You re-implement ItemizedOverlayWithFocus.draw() and ItemizedOverlayWithFocus.onDrawItem() in your own ItemizedOverlayWithFocus class. (only you'll call onDrawItem(), onDrawCar(), and call it instead from the overridden draw() method)
That's not worth it unless you want to change the offset of the Marker being drawn. e.g. I have a tower icon, and I want 10 pixels from the bottom to be the Y point so it looks like the tower is standing on the GeoPoint, not at the edge of it.
2) You create your own Markers from a Bitmap first, and set it as a Drawable Marker in the OverlayItem.setMarker() method. Try creating a a Bitmap using Canvas:
Bitmap bitmap = Bitmap.createBitmap(width, height, Config.RGB_565);
Canvas canvas = new Canvas(bitmap);
// Draw on your car on the canvas...
Then try assigning the Bitmap:
overlayItem.setMarker(new BitmapDrawable(bitmap));
Don't override draw() unless you want to draw some other stuff, and if you do ensure you super.draw() so the Marker and its Hotspot work with the gestures.
You can try also this code
Drawable newMarker = this.getResources().getDrawable(R.drawable.ic_marker);
this.mMyLocationOverlay = new ItemizedIconOverlay<OverlayItem>(items,
newMarker, "listener try null", new DefaultResourceProxyImpl(getActivity()));
mapView.getOverlays().add(mMyLocationOverlay);
I have an activity that extends MapActivity, and inside onCreate() I have this code
GeoPoint point = new GeoPoint((int)(1.3*1E6),(int)(34.45*1E6));
final MapController mc;
mc.animateTo(point);
that animates, to that point, however, when it animates, the point is in the center of the screen, and I want it to be in a fixed (X,Y) position on the screen. Is there an mc.animatetoLeftBottom(point) function?
Edit :
I used the
Projection p = mapView.getProjection();
point = p.fromPixels(50, 60);
mc.animateTo(point);
pictures:
When I start the app, it looks like this :
After I tap once on the pin, it looks like this
And, if I tap again on the pin, it will look like this:
This is how it should look like, no matter where I tap it from, or if I scroll, zoom and then tap again:
What I want is for it to automatically move to that position(see last picture) when I tap the pin
Can't you just change the GeoPoint to account for the fact, and animate to a different point?
Try this:
MapView mv = getMapView(); // fetch your map view
Projection p = mv.getProjection();
GeoPoint point = p.fromPixels(X, Y);
mc.animateTo(point);
I'm porting a Google Maps based project to Osmdroid in order to use OpenStreetMaps. The port is working OK apart from adding my overlay which consists of a number of straight lines and some text. In both projects I add the Overlay by means of a timer thread and handler calling redrawOverlay.
In the OSM project my overlay is just a grey square completely hiding the map. If I remove the call to redrawOveraly, the OSM tiles are shown OK. I've reduced the overlay code to the bare minimum of a single diagonal line in the code samples below. It works fine in the Google app, overlaying the map tile. The com.google.android.maps.Overlay has a draw method, the OSM has an onDraw, so I have in the OSM version:
private MapView mv;
private MapOverlay mmapOverlay = null;
private void redrawOverlay() {
gPt = mv.getMapCenter();
if (mmapOverlay == null)
mmapOverlay = new MapOverlay(getApplicationContext());
List<Overlay> listOfOverlays = mv.getOverlays();
listOfOverlays.clear();
listOfOverlays.add(mmapOverlay);
mv.invalidate();
}
public class MapOverlay extends org.osmdroid.views.overlay.Overlay {
public MapOverlay(Context ctx) {
super(ctx);
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas canvas, MapView mapView) {
Paint lp3;
lp3 = new Paint();
lp3.setColor(Color.RED);
lp3.setAntiAlias(true);
lp3.setStyle(Style.STROKE);
lp3.setStrokeWidth(1);
lp3.setTextAlign(Paint.Align.LEFT);
lp3.setTextSize(12);
canvas.drawLine(10, 10, 150, 150, lp3);
}
Whilst in the Google maps original I have the equivalent :
public class MapOverlay extends com.google.android.maps.Overlay {
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow,
long when) {
super.draw(canvas, mapView, shadow);
Paint lp3;
lp3 = new Paint();
.....etc.
redrawOverlay is the same except the instantiation of the overlay is just:
mmapOverlay = new MapOverlay();
All suggestions will be gratefully received
UPDATE Question for kurtzmarc:
Thanks for you help so far, I see that you are one of the authors of Osmdroid. I like what it's doing so far. I would like to suppress the 'jump to and zoom in' that you get on double tap. I'd like it to do nothing at all. I think it's probably hitting this bit in your source and doing the zoomInFixing:
private class MapViewDoubleClickListener implements GestureDetector.OnDoubleTapListener {
#Override
public boolean onDoubleTap(final MotionEvent e) {
for (int i = mOverlays.size() - 1; i >= 0; i--)
if (mOverlays.get(i).onDoubleTapUp(e, MapView.this))
return true;
final GeoPoint center = getProjection().fromPixels(e.getX(), e.getY());
return zoomInFixing(center);
}
It doesn't seem that I can override it. I'm using the 3.0.1 jar and the associated javadocs. I'm wondering if the Mapview's setTouchDelegate method would help, but there is no reference to it in the javadocs. Have you any suggestions please?
I'm not sure where you are calling redrawOverlay() from, but if you look at the MinimapOverlay you will see an example where something is drawn at a fixed location on the screen. In other words, you are drawing in screen coordinates not in map coordinates.
Example:
#Override
protected void onDraw(final Canvas pC, final MapView pOsmv) {
// Calculate the half-world size
final Rect viewportRect = new Rect();
final Projection projection = pOsmv.getProjection();
final int zoomLevel = projection.getZoomLevel();
final int tileZoom = projection.getTileMapZoom();
mWorldSize_2 = 1 << (zoomLevel + tileZoom - 1);
// Find what's on the screen
final BoundingBoxE6 boundingBox = projection.getBoundingBox();
final Point upperLeft = org.osmdroid.views.util.Mercator
.projectGeoPoint(boundingBox.getLatNorthE6(), boundingBox.getLonWestE6(),
zoomLevel + tileZoom, null);
final Point lowerRight = org.osmdroid.views.util.Mercator
.projectGeoPoint(boundingBox.getLatSouthE6(), boundingBox.getLonEastE6(), zoomLevel
+ tileZoom, null);
// Save the Mercator coordinates of what is on the screen
viewportRect.set(upperLeft.x, upperLeft.y, lowerRight.x, lowerRight.y);
// Offset into OSM coordinates
viewportRect.offset(-mWorldSize_2, -mWorldSize_2);
// Draw a line from one corner to the other
canvas.drawLine(viewportRect.left, viewportRect.top, viewportRect.right, viewportRect.bottom);
From here viewportRect represents the upper left to the lower right of the screen. You can use this to draw at any fixed points on the screen.
UPDATE:
To answer your second question - what you need to do is override onDoubleTap in your Overlay and return "true". Returning "true" indicates to the base class that you "consumed" the event and no further processing should take place. Take a look at the minimap overlay code for a good example:
http://code.google.com/p/osmdroid/source/browse/trunk/osmdroid-android/src/org/osmdroid/views/overlay/MinimapOverlay.java
We are right in the middle of overhauling the Overlays, so some of this will be handled a little better in the near future. For example, the getOverlays().clear() bug you ran into has also been reported elsewhere and we've since fixed it.