android Maps API v2 with custom markers
Asked Answered
S

9

66

I want to make maps with custom markers. In API v2 I can set icon, title, etc for markers. But I want to display title with marker at the first onset. Now title displays only when I taping the marker. In v1 was overlays, but in v2 I didn't found anything similar.

Edited: Maybe I was not clear enough. Something like Marker.showInfoWindow() in API works only for one marker. I can't show info windows for all of my markers at the same time. Anyway I need to show titles for all of my markers, without waiting while user will tap on it.

State answered 7/12, 2012 at 12:56 Comment(7)
what have you tried so far? no luck here?Origami
What do you mean? in API v1 you can do it using ItemizedOverlay and OverlayItem. But in API v2, there is no anything like this, I didn't found the way to make it. This is a very limited API.State
No. There you can set the icon, title and description. But title will appear only when you'll click on the marker. Before this you can see just icon, without title.State
i.e. you want to draw text on the map?Olivares
I want to draw text with marker (icon), i.e custom view where I can put anything I want.State
So you wanted all markers infoviews to be open at the same time?Homoeo
Warpzit: yes, that is what I wantState
N
84

I have also stumbled upon this problem. V2 API is a step forward, two steps back. Google, please add an overridable 'draw' method on the Marker or GoogleMap classes so we can customize the drawing ourselves.

A possible solution is to generate the bitmap on the fly and attach it to the marker. i.e. Create a canvas, insert the marker bitmap, draw the text next to the marker. This involves some painful calculations (the appropriate canvas size with the marker bitmap and the text next to each other). Unfortunately, there's no setIcon method in Marker, so every time the text changes, a new marker has to be created. It may be fine if you just have a marker on the map, but with dozens of markers, this may not be feasible. Also there may be memory issue on creating those bitmaps dynamically. A sample code (with just the text):

Bitmap.Config conf = Bitmap.Config.ARGB_8888; 
Bitmap bmp = Bitmap.createBitmap(200, 50, conf); 
Canvas canvas = new Canvas(bmp);

canvas.drawText("TEXT", 0, 50, paint); // paint defines the text color, stroke width, size
mMap.addMarker(new MarkerOptions()
                                .position(clickedPosition)
                                //.icon(BitmapDescriptorFactory.fromResource(R.drawable.marker2))
                                .icon(BitmapDescriptorFactory.fromBitmap(bmp))
                                .anchor(0.5f, 1)
                                    );

Hopefully, Google will add the appropriate methods so we can do this easily. Damn, I really like the new Map rotate feature in V2 API.

Novara answered 14/12, 2012 at 18:1 Comment(3)
it's a little crooked, but for now I think this is the best solution.State
Great solution to a big flaw introduced in v2. How did they miss this when Trulia, the app they used to demonstrate Maps v2, uses text over a bitmap on their Markers?Impassible
A Marker.setIcon() method is now available in the most recent version of the Maps API (as of May 15, 2013) - developers.google.com/maps/documentation/android/reference/com/…Revelationist
I
49

Finally did it. So what you do is have a background image (in my case i just use a blue rectangle). Create a marker like so:

Marker myLocMarker = map.addMarker(new MarkerOptions()
            .position(myLocation)
            .icon(BitmapDescriptorFactory.fromBitmap(writeTextOnDrawable(R.drawable.bluebox, "your text goes here"))));

Notice the writeTextOnDrawable() Method:

private Bitmap writeTextOnDrawable(int drawableId, String text) {

    Bitmap bm = BitmapFactory.decodeResource(getResources(), drawableId)
            .copy(Bitmap.Config.ARGB_8888, true);

    Typeface tf = Typeface.create("Helvetica", Typeface.BOLD);

    Paint paint = new Paint();
    paint.setStyle(Style.FILL);
    paint.setColor(Color.WHITE);
    paint.setTypeface(tf);
    paint.setTextAlign(Align.CENTER);
    paint.setTextSize(convertToPixels(context, 11));

    Rect textRect = new Rect();
    paint.getTextBounds(text, 0, text.length(), textRect);

    Canvas canvas = new Canvas(bm);

    //If the text is bigger than the canvas , reduce the font size
    if(textRect.width() >= (canvas.getWidth() - 4))     //the padding on either sides is considered as 4, so as to appropriately fit in the text
        paint.setTextSize(convertToPixels(context, 7));        //Scaling needs to be used for different dpi's

    //Calculate the positions
    int xPos = (canvas.getWidth() / 2) - 2;     //-2 is for regulating the x position offset

    //"- ((paint.descent() + paint.ascent()) / 2)" is the distance from the baseline to the center.
    int yPos = (int) ((canvas.getHeight() / 2) - ((paint.descent() + paint.ascent()) / 2)) ;  

    canvas.drawText(text, xPos, yPos, paint);

    return  bm;
}



public static int convertToPixels(Context context, int nDP)
{
    final float conversionScale = context.getResources().getDisplayMetrics().density;

    return (int) ((nDP * conversionScale) + 0.5f) ;

}

Thanks to Arun George: Add text to image in android programmatically

Infeasible answered 14/9, 2013 at 11:9 Comment(2)
How would you use this to make text appear above the marker/bitmap?Wafture
canvas.drawtext is cutting of the text. Full text is not drawing #39307224Extremism
R
16

Seems like your question was finally answered at a Google I/O session.

Have a look at http://googlemaps.github.io/android-maps-utils/

It has:

Marker clustering — handles the display of a large number of points

Heat maps — display a large number of points as a heat map

IconGenerator — display text on your Markers (see screenshot)

Markers made using the library

Very importantly it can be modified on any thread so handling many markers is a breeze

Rarely answered 23/11, 2014 at 16:19 Comment(0)
S
9

I am not sure which you are trying to achieve: having the info window show up without the user have to tap on the marker, or using a completely different view for the info window (or perhaps both).

To show the info window without requiring a user tap:

I haven't tested this myself, but I'm guessing Marker.showInfoWindow() would do the trick (assuming the Marker's visibility is already true.

To provide a custom view for the InfoWindow

There are two options here and you should refer to the documentation on GoogleMap.InfoWindowAdapter:

public static interface GoogleMap.InfoWindowAdapter

Provides views for customized rendering of info-windows.

Methods on this provider are called when it is time to show an info window for a marker, regardless of the cause (either a user gesture or a programmatic call to showInfoWindow(). Since there is only one info window shown at any one time, this provider may choose to reuse views, or it may choose to create new views on each method invocation.

When constructing an info-window, methods in this class are called in a defined order. To replace the default info-window, override getInfoWindow(Marker) with your custom rendering. To replace just the info-window contents, inside the default info-window frame (the callout bubble), leave the default implementation of getInfoWindow(Marker) in place and override getInfoContents(Marker) instead.

Basically, whether you override getInfoWindow() or getInfoContents() will depend on whether or not you just wish to customize what you see inside the callout bubble, or whether you wish to customize the entire info window view, including an alternative to the callout bubble.

One caveat: I believe when you override these methods, it performs a simple rendering of what the view looks like at the time getInfoWindow() or getInfoContents() is called. I myself am interested in trying to replicate the look of the native Google Maps Android app which has a little "directions" icon next to the name of the place. One of the problems I believe (see here: https://mcmap.net/q/138743/-adding-a-button-to-a-custom-infowindowadapter-view-that-can-register-clicks) is that if you have something like a button in your view, it may not behave like a button because of the static rendering.

Strengthen answered 11/12, 2012 at 2:45 Comment(3)
Thank you for the answer, I have another small question, what if I want the marker to contain custom data for the content, something other than the title/icon. Is there anyway I could extend the marker or the markerOptions to add custom data there for the adapter?(like rating if my content window contains a ratingbar) The solution I find now is to have both the marker and the data in separate objects liked in one class.Faultless
Maybe I should edit my question. Marker.showInfoWindow() works only for one marker. I can't make to show info windows for several markers at the same time.State
Not to answer this question but really helpfull information. It helped me. +1Walkway
B
4

Customize the marker image

You can replace the default marker image with a custom marker image, often called an icon. Custom icons are always set as a BitmapDescriptor, and defined using one of four methods in the BitmapDescriptorFactory class.

fromAsset(String assetName) Creates a custom marker using an image in the assets directory.

fromBitmap (Bitmap image) Creates a custom marker from a Bitmap image.

fromFile (String path) Creates a custom icon from a file at the specified path.

fromResource (int resourceId) Creates a custom marker using an existing resource. The below snippet creates a marker with a custom icon.

 private static final LatLng MELBOURNE = new LatLng(-37.813, 144.962);
 private Marker melbourne = mMap.addMarker(new MarkerOptions()
                        .position(MELBOURNE)
                        .title("Melbourne")
                        .snippet("Population: 4,137,400")
                        .icon(BitmapDescriptorFactory.fromResource(R.drawable.arrow)));
Bleacher answered 12/1, 2015 at 12:49 Comment(0)
A
2

This simple code works to display the title without requiring a click event:

googleMap.addMarker(new MarkerOptions()
        .position(latLng)
        .title(String title))
        .showInfoWindow();
Aqueous answered 18/1, 2013 at 4:13 Comment(1)
But if you have more than 1 marker this method showInfoWindow() will work just for last oneCostplus
M
1

Google has come out with the IconGenerator class which makes adding custom icon easy.

IconGenerator iconGenerator = new IconGenerator(mContext);
Bitmap bitmap = iconGenerator.makeIcon("Text Of Icon");
mMap.addMarker(new MarkerOptions()
                      .position(latlng)
                      .title("Location")
                      .icon(BitmapDescriptorFactory.fromBitmap(bitmap)));
Mathews answered 20/2, 2019 at 16:15 Comment(3)
which package or library does this class come from?!Postaxial
it says Cannot resolve symbol 'IconGenerator' for AndroidGirardo
@Girardo - this requires the library here - github.com/googlemaps/android-maps-utilsGualterio
M
0

Why don't you keep an array of the markers then when it comes to laoding the markers, iterate through them calling showInfoWindow(). May not be the most elegant solution but it does what you are saying I think.

Milomilon answered 13/12, 2012 at 10:21 Comment(1)
You call showInfoWindow() for one marker - info window appears. Then you call showInfoWindow() for the second marker - window appears for the second and disappears for the first. That's the problem.State
D
-6

I solved this problem by making my own markers with a picture editor which has the details below. It took some time to make, but it works.

I used Photoshop and 53x110px markers.

an example marker that I made

Dacosta answered 24/1, 2013 at 4:7 Comment(1)
Did you add names to each marker in Phoroshop or do you add it dynamically in Android?Marilee

© 2022 - 2024 — McMap. All rights reserved.