I am developing Google map in my application but its not showing map only showing grid line ,Please anyone help me what is problem is that?
And I am drawing text over bubbles,when more than 2 bubble lie same places,in that case text overlapping to each other.
After changing API key Map will be showing but my second problem still remaining.I have to draw bubbles on Map and text (size of property on that bubble) suppose there are size of list 4 then 4 should be draw on bubble.I have been implemented these but there is no desire output is showing.
When more than 2 property on same position and each have more than 2 list size then text on bubble overlapp to eachother sorry for my explanation I am using this code -
drawable = this.getResources().getDrawable(R.drawable.bluedot);
drawable1 = this.getResources().getDrawable(R.drawable.bluedot_large);
overlay = new GoogleMapViewOverlay(drawable,mapView,activity);
//GoogleMapViewOverlay method is as:-
public GoogleMapViewOverlay(Drawable drawable, MapView mapView,
Activity activity2)
{
//super(drawable);
super(boundCenterBottom(drawable));
setLastFocusedIndex(-1);
populate();
arrayList1 = new ArrayList<Applicationdataset>() ;
items = new ArrayList<OverlayItem>();
marker = drawable;
mContext = mapView.getContext();
mc = mapView.getController();
this.activity = activity2;
DB = new DatabaseHelper(activity2);
}
//add item as
if(point != null)
{
if(arrayList.get(i).getUnitstotal().equalsIgnoreCase("1"))
{
oi = overlay.createItem(i);
System.out.println("listing when 1 value is"+arrayList.get(i).getUnitstotal());
overlay.addItem(oi);
}
else if(!arrayList.get(i).getUnitstotal().equalsIgnoreCase("1"))
{
oi = overlay.createItem(i);
System.out.println("listing when more value is "+ arrayList.get(i).getUnitstotal());
if(overlay!=null)
{
overlay.addItem(oi);
//overlay.draw(canvas, mapView, shadow);
}
}
}
//draw method for text draw over bubbles
#Override
public boolean draw(Canvas canvas, MapView mapView, boolean shadow, long when )
{
super.draw(canvas, mapView, false);
arrayList1 = arrayList;
for (int index = 0; index < items.size(); index++)
{
OverlayItem item = items.get(index);
GeoPoint point = item.getPoint();
Point ptScreenCoord = new Point();
mapView.getProjection().toPixels(point, ptScreenCoord);
//Paint
Paint paint = new Paint();
paint.setStyle(Style.STROKE);
paint.setTextAlign(Paint.Align.CENTER);
paint.setTypeface((Typeface.defaultFromStyle(Typeface.BOLD)));
paint.setTextSize(20);
paint.setColor(Color.WHITE);
paint.setFilterBitmap(false);//true
if(arrayList.get(index).getUnitstotal().equalsIgnoreCase("1"))
canvas.drawText("", ptScreenCoord.x, ptScreenCoord.y-20,paint);
else
{
canvas.drawText(arrayList.get(index).getUnitstotal().toString(), ptScreenCoord.x, ptScreenCoord.y-40, paint);
}
}
return true;
}
Most Probably you havent fetched google map api key, please fetch it according to the instructions on following link, and then try:
https://developers.google.com/maps/documentation/android/mapkey
Related
My mapview (osmbonuspack) rotates into the walking direction.
How can I rotate the marker's title on the map so that they are horizontal - i.e. easy for reading? I see that the marker itself does not need any rotation while the map is turned.
Any change in the walking direction will result in the right rotation of the map using:
mapview.setMapOrientation( (float) -headingByCompass);
So on any change, I first find all Markers on the mapview. Then I tried to rotate them ... but the title direction is still the same.
marker.setRotation( rotation);
To be sure: this is about the text that is near the inverted eye drop. This is not the info in the bubble.
The Marker itself has no label attached to it. So, I created a subclass of Marker called MarkerWithLabel. In this subclass the title or label is drawn.
When the map is rotated, the rotation is subsequently passed to all MarkerWithLabel objects. A subsequent invalidate on the mapview will make the changes visible. So, the markers and the labels are always horizontal for easy reading.
The MarkerWithLabel class it:
public class MarkerWithLabel extends Marker {
Paint textPaint = null;
String mLabel = null;
float rotation = 0.0f;
public MarkerWithLabel( MapView mapView, String label) {
super( mapView);
mLabel = label;
textPaint = new Paint();
textPaint.setColor( Color.RED);
textPaint.setTextSize( WaypointActivity.textSizeCanvas25sp);
textPaint.setAntiAlias(true);
textPaint.setTextAlign(Paint.Align.LEFT);
setTitle( label);
}
public void draw( final Canvas c, final MapView osmv, boolean shadow) {
draw( c, osmv);
}
public void draw( final Canvas c, final MapView osmv) {
super.draw( c, osmv, false);
Point p = this.mPositionPixels; // already provisioned by Marker
if( rotation <= -1 || rotation >= 1) { // could be left out
c.save();
c.rotate( rotation, p.x, p.y);
c.drawText( getTitle(), p.x, p.y+20, textPaint);
c.restore();
} else {
c.drawText( getTitle(), p.x, p.y+20, textPaint);
}
}
}
Finding all MarkerWithLabel instances is easy:
List<Overlay> markersOnTheMap = mv.getOverlays();
if( markersOnTheMap == null || markersOnTheMap.isEmpty()) {
return ;
}
for( int i = 0; i < markersOnTheMap.size(); i++) {
Object o = markersOnTheMap.get( i);
if( o instanceof MarkerWithLabel) {
MarkerWithLabel m = (MarkerWithLabel) o;
m.rotation = rotation;
}
}
Hope this helps you.
As OSMBonusPack Marker try to mimic Google Maps API, you can refer to https://developers.google.com/maps/documentation/android/marker
=> You will have description of Flat / Billboard orientation, and Rotation.
If you just want the Marker to be aligned with the screen, this is the default behaviour, just do nothing (no rotation).
BTW, what are you calling the "Marker title"? The title shown in the bubble?
I works with OSMdroid. I extended the Overlay class and I overridden the draw method to my needs. And I have a problem with placing of markers. When I display them for the first time they have wrong location. But when I start zooming they move and after couple of zooms they have correct localization.
Here is my code:
protected final Rect mRect = new Rect();
protected Point mScreenPts = new Point();
#Override
protected void draw(Canvas c, MapView osmv, boolean shadow) {
Projection pj = osmv.getProjection();
synchronized (mInternalItemList) {
if (shadow && !mInternalItemList.isEmpty()) {
for(int i = 0; i < mInternalItemList.size(); i++) {
CustomizedItem customized = mInternalItemList.get(i);
pj.toMapPixels(new GeoPoint(customized.getLatitude(),
customized.getLongitude()), mScreenPts);
boundToHotspot(customized.getDrawable(), HotspotPlace.LOWER_LEFT_CORNER);
Drawable draw = customized.getDrawable();
draw.copyBounds(mRect);
draw.setBounds(mRect.left + mScreenPts.x, mRect.top + mScreenPts.y,
mRect.right + mScreenPts.x, mRect.bottom + mScreenPts.y);
draw.draw(c);
draw.setBounds(mRect);
}
}
}
}
I'm using an Overlay to mark areas on Google Maps by drawing a shape of ten thousands of GeoPoints I get from any source. This works and looks like this:
#Override
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, false);
Projection projection = mapView.getProjection();
List<Zone> zones = ApplicationContext.getZones();
path.rewind();
for (Zone zone : zones) {
paint.setDither(true);
paint.setStyle(Style.FILL);
paint.setAlpha(40);
MultiPolygon multiPolygon = zone.getMultiPolygon();
List<Polygon> polygons = multiPolygon.getPolygons();
for (Polygon polygon : polygons) {
for (List<Coordinate> coordinates : polygon.getCoordinates()) {
for (int i = 0; i < coordinates.size(); i++) {
Point p = new Point();
projection.toPixels(new GeoPoint((int)(coordinates.get(i).getLatitude() * 1E6), (int)(coordinates.get(i).getLongitude() * 1E6)), p);
if (i == 0) {
path.moveTo(p.x, p.y);
}
else {
path.lineTo(p.x, p.y);
}
}
}
}
}
canvas.drawPath(path, paint);
}
The problem is that this is very resource consuming. Every time one scrolls or moves the map on MapView, the path has to be calculated over and over again, because the pixel coordinates have been changed. The drawn area could become so big that the scrolling on the MapView is so slow that it is functional unusable.
My ideas are
to somehow cache the "shape" the path generates and just redraw it
when the zoom level changes on the MapView.
to somehow draw the painting on an "on the fly"-Bitmap to use it as Overlay (maybe as ItemizedOverlay), listen for MapView scrolling and move the bitmap by the scrolled distance.
I'm not sure if there are better methods.
Any ideas how I could solve this problem?
(I'm using Google Maps API 1 and can't change).
Before resorting to trying to figure out how to match the map's movement, there are some optimizations to your current code that will probably yield significant savings. In particular, these two lines inside your inner loop is executed the most times, but fairly expensive to execute (two memory allocations, floating point multiplies, and four method calls).
Point p = new Point();
projection.toPixels(new GeoPoint((int)(coordinates.get(i).getLatitude() * 1E6), (int)(coordinates.get(i).getLongitude() * 1E6)), p);
First, you only ever need one Point object, so avoid allocating it in your loop. Move it to just below your path.rewind();
Second, if you pre-computed your coordinates as GeoPoints instead of computing them each time, you would save a lot of processing in your draw routine. You can also get rid of that if statement with a little work. Assuming you preconvert your list of coordinate to a list of GeoPoint, and make it available through polygon.getGeoCoordinates(), you could end up with your inner loops looking like -
for (List<GeoPoint> geoCoordinates : polygon.getGeoCoordinates()) {
projection.toPixels(geoCoordinates.get(0),p);
path.moveTo(p.x, p.y); // move to first spot
final List<GeoPoint> lineToList = geoCoordinates.sublist(1,geoCoordinates.size()); // A list of all the other points
for(GeoPoint gp : lineToList) {
projection.toPixels(gp, p);
path.lineTo(p.x, p.y);
}
}
And that will run a lot faster than what you were doing before.
After tinkering around in the last days I found a possible solution (and I don't think there is a better one) to not draw the path over and over again but move it to the current position.
The difficult part was to figure out how to cache the drawn shape to not calculate it over and over again. This can be done by using a Matrix. With this Matrix (I imagine this as some kind of "template") you can manipulate the points coordinates inside the path. The first time (when someone starts moving the Map) I draw the area as usual. When it tries to calculate it the second time or more, I don't redraw the shape but I manipulate the path by calculating the "delta" from the current point to the last point. I know what the current point is, because I always map the original GeoPoint (which always stays the same) to the point which results from the current projection. The "delta" needs to be set as Matrix. After that I transform the path by using this new Matrix. The result is really very fast. The scrolling of the Map is as fast as without using an Overlay.
This looks like this (this is no production code, and it cannot deal with zooming yet, but it shows the principle I use as basis for my optimizations):
public class DistrictOverlay extends Overlay {
// private final static String TAG = DistrictOverlay.class.getSimpleName();
private Paint paint = new Paint();
private Path path = new Path();
private boolean alreadyDrawn = false;
private GeoPoint origGeoPoint;
Point p = new Point();
Point lastPoint = new Point();
#Override
public void draw(android.graphics.Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, false);
Projection projection = mapView.getProjection();
List<Zone> zones = ApplicationContext.getZones();
if (!alreadyDrawn) {
path.rewind();
for (Zone zone : zones) {
if (!zone.getZoneId().equals(MenuContext.getChosenZoneId())) {
continue;
}
String dateString = zone.getEffectiveFrom().trim().replace("CEST", "").replace("GMT", "").replace("CET", "").replace("MESZ", "");
if (DateUtil.isBeforeCurrentDate(dateString)) {
paint.setColor(Color.RED);
} else {
paint.setColor(Color.GREEN);
}
paint.setDither(true);
paint.setStyle(Style.FILL);
paint.setAlpha(40);
MultiPolygon multiPolygon = zone.getMultiPolygon();
List<Polygon> polygons = multiPolygon.getPolygons();
for (Polygon polygon : polygons) {
for (List<GeoPoint> geoPoints : polygon.getGeoPoints()) {
projection.toPixels(geoPoints.get(0), p);
path.moveTo(p.x, p.y);
origGeoPoint = new GeoPoint(geoPoints.get(0).getLatitudeE6(), geoPoints.get(0).getLongitudeE6());
lastPoint = new Point(p.x, p.y);
final List<GeoPoint> pathAsList = geoPoints.subList(1, geoPoints.size());
for (GeoPoint geoPoint : pathAsList) {
projection.toPixels(geoPoint, p);
path.lineTo(p.x, p.y);
}
}
}
}
}
else {
projection.toPixels(origGeoPoint, p);
Matrix translateMatrix = new Matrix();
translateMatrix.setTranslate(p.x - lastPoint.x, p.y - lastPoint.y);
path.transform(translateMatrix);
lastPoint = new Point(p.x, p.y);
}
canvas.drawPath(path, paint);
if (!path.isEmpty()) {
alreadyDrawn = true;
}
}
#Override
public boolean onTap(GeoPoint p, MapView mapView) {
return true;
}
}
This part of code takes some coordinates and draws a tag icon in the map.
private void drawMapLocations(Canvas canvas, MapView mapView) {
Iterator<MapTagLocation> iterator = mapTab.getMapLocations().iterator();
Point screenCoords = new Point();
while (iterator.hasNext()) {
MapTagLocation location = iterator.next();
mapView.getProjection().toPixels(location.getPoint(), screenCoords);
canvas.drawBitmap(tagIcon, screenCoords.x - tagIcon.getWidth() / 2, screenCoords.y - tagIcon.getHeight(), null);
}
}
Now I want to make a method that removes or replace a specific tag in the map. Is there any way?
*The tagIcon is a Bitmap.
I need to draw text on a custom marker which are quite a lot in number. But the problem is that when I draw the text in the Overridden on draw, all the overlay items text appears to be in one layer above the markers and does not seem synched when the map is zoomed in or zoomed out. Previously I was calling the populate when each item was added and this was working fine but it was too slow. Any help?
In my custom class that extends from ItemizedOverlay, the constructor is as follows, where I set the custom marker:
public HotelMapFilterOverlay(Drawable defaultMarker, final Context con) {
super(boundCenterBottom(defaultMarker));
this.marker = defaultMarker;
this.con = con;
}
and the overridden draw method is as follows:
#Override
public void draw(Canvas canvas, MapView mapView, boolean shadow) {
super.draw(canvas, mapView, shadow);
Bitmap bmp = ((BitmapDrawable) marker).getBitmap();
Paint textPaint = new Paint();
textPaint.setColor(Color.WHITE);
textPaint.setTextSize(16f);
textPaint.setTypeface(Typeface.create(Typeface.SANS_SERIF, 1));
textPaint.setStyle(Paint.Style.FILL);
Point screenPts = new Point();
float bmpWidth = bmp.getWidth();
float bmpHeight = bmp.getHeight();
float left;
float top;
int total = mOverlayItems.size();
for (int index = 0; index < total; index++) {
gp = mOverlayItems.get(index).getPoint();
mapView.getProjection().toPixels(gp, screenPts);
left = screenPts.x - (bmpWidth / 2);
top = screenPts.y - bmpHeight;
// draw text
this.title = mOverlayItems.get(index).getTitle();
canvas.drawText(this.title, left + 8, top + 30,textPaint);
}
}
and I calling the populate only once to make this efficient like
public void callPopulate(){
populate();
}
To get your marker text to appear separately over each marker without all of it layering on top of the markers, you need to draw the markers yourself and remove super.draw(canvas, mapView, shadow).
To draw the markers you have most of the code already! Just create a new Paint markerPaint = new Paint() object and add the following in your for-loop before you draw your text:
canvas.drawBitmap(bmp, screenPts.x-(bmp.getWidth()/2), screenPts.y-(bmp.getHeight()), markerPaint);
This way the marker is drawn then its text is drawn on top.
With respect to 'populate' you should call this just after you add all the items to your ItemizedOverlay.