Map Markers with text in Google Maps Android API v2
Asked Answered
P

7

21

I have came up with this post but it is for the deprecated Google Maps API

http://tech.truliablog.com/2012/02/23/custom-map-markers-for-android-google-maps/

In the new API, I could not find an easy way to do this. In fact, I could not do it at all.

Basicly I want to have TextViews as a Marker on the map with 9Patch drawable as a background of the text. Trulia is still doing it with the new API v2 in their current app. You can check it here

Trulia current app

How can I do this?

Paramilitary answered 24/7, 2013 at 14:50 Comment(5)
you can use info window. developers.google.com/maps/documentation/android/markerZeb
Did you look at the the picture above? Do the little markers seem to be info windows to you?Paramilitary
It looks like info window to me. If not what is that you are looking for.?. Also did you check the link posted.?Zeb
No they are not, they are markers. When you click them, they show info windows.Paramilitary
check the link posted has details regarding markers and info window.Zeb
A
40

Chris Broadfoot created a utility library that does exactly that.

The library is available here: https://github.com/googlemaps/android-maps-utils

Also see this short video: http://www.youtube.com/watch?v=nb2X9IjjZpM

Anurag answered 24/7, 2013 at 18:31 Comment(0)
G
18

It can be simply achieved using this useful lib provided by google.

IconGenerator icg = new IconGenerator(this);
icg.setColor(Color.GREEN); // green background 
icg.setTextAppearance(R.style.BlackText); // black text 
Bitmap bm = icg.makeIcon("200 mi");

In style.xml

<style name="BlackText" parent="TextDefault">
    <item name="android:textColor">@color/black</item>
</style>

http://googlemaps.github.io/android-maps-utils/javadoc/

http://googlemaps.github.io/android-maps-utils/

https://github.com/googlemaps/android-maps-utils

you can set up upper links in your project from this link

Goto answered 26/10, 2017 at 14:28 Comment(1)
Made my day. Thank you so muchEarthshine
C
6

As far as I know, this is not currently supported by the google maps api v2. What you can do, on the other hand, is dynamically create the bitmap for your marker, and write the value you want to show in it. Alas, there may easily be performance issues if you happen to have plenty of pins.

Canvas canvas = new Canvas(bitmap);
canvas.drawText("Your text", textXOffset, textYOffset, mPictoPaint);
MarkerOptions options = new MarkerOptions().position([…]).icon(BitmapDescriptorFactory.fromBitmap(bitmapResult));
Marker newMarker = map.addMarker(options);

Note that bitmap needs to be mutable. Also you will have to scale the base image (probably using a 9.patch) to your need.

Captain answered 24/7, 2013 at 15:23 Comment(6)
I am trying to do something like this for hours. I already did this but I cannot add 9Patch drawable to the background.Paramilitary
Would this help ? Although this might not be mutable, so there may be some additional processing to do.Captain
Ok this link is also helpful but there are x and y variables there. I do not know the height of the actual text before draw the 9patch drawable. How can I make use of the code in the last link and use drawText()?Paramilitary
Is your text singleLine or multiLine ? The former is rather easy, you could use Paint.measureText for instance to get the size your text will take once display, and deduce the size of your bitmap (adding the extra padding you'll need). multiLine is a real pain and I would recommend to avoid it if you can. Another solution for the singleLine version is the use of a StaticLayout to, once again, get the size your text will take on screen.Captain
Certainly this is an optimal way to do this, but can also be achieved using Views.Cantus
It is actually single line. Thank you for the answer. I was going to try that but the answer of @Anurag is very good. It works out of the box. I searched something like that but I could not find earlier.Paramilitary
F
5

I know this question is old but I'll post my answer here in case it helps someone.

None of the above solutions were working for me because

  • I already have custom icons for markers in my app

  • My app display potentially thousands of different marker titles so creating that many images in memory would be a performance problem

  • As the marker icons become bigger, the map becomes very quickly unreadable

  • I wanted the titles to show only if there is room, potentially hiding if not enough room to display

I found no solution on the internet so I rolled up my sleeves and made this library which solves my problem, hopefully it will help others too:

https://github.com/androidseb/android-google-maps-floating-marker-titles

Here is a preview of how it works:

preview

Footless answered 12/8, 2018 at 18:10 Comment(0)
S
2

by referring to Google's sample code

IconGenerator iconFactory = new IconGenerator(this);    
        iconFactory.setColor(Color.CYAN);
        addIcon(mMap, iconFactory, "Custom color", new LatLng(-33.9360, 151.2070));

addIcon() Method here:

private void addIcon(GoogleMap googleMap, IconGenerator iconFactory, CharSequence text, LatLng position) {
        MarkerOptions markerOptions = new MarkerOptions().
                icon(BitmapDescriptorFactory.fromBitmap(iconFactory.makeIcon(text))).
                position(position).
                anchor(iconFactory.getAnchorU(), iconFactory.getAnchorV());

        googleMap.addMarker(markerOptions);
    }
Sarcophagus answered 1/10, 2019 at 2:31 Comment(0)
M
0

If you use Clusters, a behaviour is slightly different.

Looking at https://medium.com/@yilmazvolkan/custom-map-marker-8b136212d766 and here, I wrote so.

styles.xml:

<!-- Google Maps marker -->
<style name="MarkerText">
    <item name="android:textSize">12sp</item>
    <item name="android:textColor">#f0f0f0</item>
</style>

marker_bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android"
    android:shape="rectangle"
    >

    <solid android:color="#3232a0" />
    <corners android:radius="18dp" />
</shape>

Fragment:

private var clusterManager: ClusterManager<SomeClusterItem>? = null
private var clusterRenderer: MarkerClusterRenderer<SomeClusterItem>? = null
private var unselectedBitmap: BitmapDescriptor? = null
private var iconGenerator: IconGenerator? = null
private var selectedItem: SomeClusterItem? = null

override fun onMapReady(googleMap: GoogleMap) {
    this.googleMap = googleMap
    ...

    unselectedBitmap =
        BitmapUtils.bitmapDescriptorFromVector(context!!, R.drawable.unselected_item)

    // Create a text marker background.
    iconGenerator = IconGenerator(context!!)
    iconGenerator!!.setTextAppearance(R.style.MarkerText)
    val markerBackground = ContextCompat.getDrawable(context!!, R.drawable.marker_bg)
    iconGenerator!!.setBackground(markerBackground)

    clusterManager = ClusterManager(context!!, googleMap)
    clusterRenderer = MarkerClusterRenderer(context!!, googleMap, clusterManager!!,
        unselectedBitmap!!)
    clusterManager!!.renderer = clusterRenderer

    ...
    // Create a list of markers.
    val boundsBuilder = LatLngBounds.Builder()
    ...

    // Show clusters and markers.
    clusterManager!!.cluster()

    clusterManager!!.setOnClusterItemClickListener { item ->
        // Deselect selected marker.
        // See https://mcmap.net/q/658634/-how-to-change-the-clicked-marker-icon-using-android-maps-utils.
        if (selectedItem != null) {
            deselectMarker(selectedItem)
        }
        selectedItem = item
        selectMarker(selectedItem!!, iconGenerator)
        // Show info window. See GoogleMap.InfoWindowAdapter.
        false
    }
    clusterManager!!.setOnClusterClickListener {
        deselectMarker(selectedItem)
        true
    }


private fun selectMarker(item: SomeClusterItem,
                         iconGenerator: IconGenerator) {
    // Generate a text marker.
    val icon = iconGenerator.makeIcon(item.title)
    val bitmapDescriptor = BitmapDescriptorFactory.fromBitmap(icon)
    clusterRenderer?.getMarker(item)?.setIcon(bitmapDescriptor)
}

private fun deselectMarker(item: SomeClusterItem?) =
    clusterRenderer?.getMarker(item)?.setIcon(unselectedBitmap)

Then you will see these pictures (all items are not selected and one item is selected).

enter image description here enter image description here

Note that InfoWindow is shown. To customize info window, see https://mcmap.net/q/265603/-android-google-maps-v2-how-to-add-marker-with-multiline-snippet.

To remove info window, just return true in an appropriate method (see Hide markers info window in android google maps API v2).

clusterManager!!.setOnClusterItemClickListener { item ->
    ...
    true
}

enter image description here

Motorman answered 24/3, 2020 at 14:24 Comment(0)
S
0

A working solution. For MarkerOptions object:

        markerOptions = new MarkerOptions()
                .position(posPrm)
                .title("" + order_id)
                .snippet(sLcl2)
                icon(giveMeBitmapDescriptor(mapsActivity,R.drawable.route_marker))
        ;

And the method:

private BitmapDescriptor giveMeBitmapDescriptor(Context context,
        int iconPrm) {
    Drawable background = ContextCompat.getDrawable(context, iconPrm);
    background.setBounds(0, 0, background.getIntrinsicWidth(), background.getIntrinsicHeight());
    Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(), background.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    background.draw(canvas);
    Rect r = new Rect();
    canvas.getClipBounds(r);
    int cHeight = r.height();
    int cWidth = r.width();
    Paint paint = new Paint();
    paint.setTextAlign(Paint.Align.LEFT);
    paint.getTextBounds("text", 0, "text".length(), r);
    float x = cWidth / 2f - r.width() / 2f - r.left;
    float y = cHeight / 2f + r.height() / 2f - r.bottom;
    canvas.drawText("text", x, y, paint);
    return BitmapDescriptorFactory.fromBitmap(bitmap);
}

Also this action should run in UI thread otherwize it doesnt claim anything and draws icon without text on it.

Stricken answered 6/4, 2021 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.