带有自定义标记的 android Maps API v2

Posted

技术标签:

【中文标题】带有自定义标记的 android Maps API v2【英文标题】:android Maps API v2 with custom markers 【发布时间】:2012-11-25 15:48:07 【问题描述】:

我想制作带有自定义标记的地图。在 API v2 中,我可以为标记设置图标、标题等。但我想在第一次开始时显示带有标记的标题。现在标题仅在我点击标记时显示。在 v1 中是叠加层,但在 v2 中我没有发现任何类似的东西。

已编辑: 也许我不够清楚。 API 中的 Marker.showInfoWindow() 之类的东西仅适用于一个标记。我无法同时显示所有标记的信息窗口。无论如何,我需要为我的所有标记显示标题,而无需等待用户点击它。

【问题讨论】:

到目前为止您尝试过什么?运气不好here? 什么意思?在 API v1 中,您可以使用 ItemizedOverlay 和 OverlayItem 来完成。但是在 API v2 中,没有这样的东西,我没有找到制作它的方法。这是一个非常有限的 API。 没有。在那里你可以设置图标、标题和描述。但是只有当你点击标记时才会出现标题。在此之前,您只能看到图标,没有标题。 即你想在地图上画文字吗? 我想用标记(图标)绘制文本,即自定义视图,我可以在其中放置我想要的任何东西。 【参考方案1】:

我也偶然发现了这个问题。 V2 API 是前进了一步,后退了两步。谷歌,请在 Marker 或 GoogleMap 类上添加一个可覆盖的“draw”方法,以便我们自己自定义绘图。

一种可能的解决方案是动态生成位图并将其附加到标记上。即创建一个画布,插入标记位图,在标记旁边绘制文本。这涉及一些痛苦的计算(适当的画布大小与标记位图和文本彼此相邻)。不幸的是,Marker 中没有 setIcon 方法,因此每次文本更改时,都必须创建一个新的标记。如果您在地图上只有一个标记可能会很好,但如果有几十个标记,这可能不可行。动态创建这些位图也可能存在内存问题。示例代码(仅包含文本):

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)
                                    );

希望 Google 会添加适当的方法,以便我们轻松完成此操作。该死,我真的很喜欢 V2 API 中的新地图旋转功能。

【讨论】:

有点歪,但目前我认为这是最好的解决方案。 很好地解决了 v2 中引入的一个大缺陷。当他们用来演示 Maps v2 的应用程序 Trulia 在其标记上的位图上使用文本时,他们怎么会错过这一点? 最新版本的 Maps API(截至 2013 年 5 月 15 日)现在提供 Marker.setIcon() 方法 - developers.google.com/maps/documentation/android/reference/com/…【参考方案2】:

终于做到了。所以你要做的是有一个背景图像(在我的例子中,我只使用一个蓝色矩形)。 像这样创建一个标记:

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

注意 writeTextOnDrawable() 方法:

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) ;


感谢阿伦·乔治: Add text to image in android programmatically

【讨论】:

如何使用它使文本出现在标记/位图上方? canvas.drawtext 正在剪切文本。全文未绘制***.com/questions/39306724/… 完美。谢谢 你真是太棒了......谢谢。【参考方案3】:

您的问题似乎终于在 Google I/O 会议上得到解答。

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

它有:

标记聚类——处理大量点的显示

热图 - 将大量点显示为热图

IconGenerator — 在标记上显示文本(见屏幕截图)

非常重要的是,它可以任何线程上进行修改,因此处理许多标记变得轻而易举

【讨论】:

【参考方案4】:

我不确定您要实现的目标是:让信息窗口在用户无需点击标记的情况下显示,或者为信息窗口使用完全不同的视图(或两者兼而有之)。

无需用户点击即可显示信息窗口:

我自己还没有测试过这个,但我猜Marker.showInfoWindow() 可以解决问题(假设标记的可见性已经是true

为 InfoWindow 提供自定义视图

这里有两个选项,你应该参考GoogleMap.InfoWindowAdapter上的文档:

公共静态接口 GoogleMap.InfoWindowAdapter

提供视图 信息窗口的自定义渲染。

在显示信息时调用此提供程序上的方法 标记窗口,无论原因如何(用户手势或 对 showInfoWindow() 的编程调用。因为只有一个信息 任何时候显示的窗口,此提供者可以选择重用视图, 或者它可以选择在每个方法调用上创建新视图。

在构建信息窗口时,会调用此类中的方法 定义的顺序。要替换默认信息窗口,请覆盖 getInfoWindow(Marker) 与您的自定义渲染。仅替换 信息窗口内容,在默认信息窗口框架内( 标注气泡),保留默认实现 getInfoWindow(Marker) 到位并覆盖 getInfoContents(Marker) 而是。

基本上,您是否覆盖 getInfoWindow()getInfoContents() 将取决于您是否只想自定义您在标注气泡中看到的内容,或者您​​是否希望自定义整个信息窗口视图,包括替代标注气泡。

一个警告:我相信当您覆盖这些方法时,它会简单地呈现视图在调用 getInfoWindow()getInfoContents() 时的样子。我本人有兴趣尝试复制本机 Google Maps Android 应用程序的外观,该应用程序的地点名称旁边有一个小“方向”图标。我认为其中一个问题(参见此处:https://***.com/a/13713536/129475)是,如果您的视图中有类似按钮的东西,由于静态渲染,它的行为可能不像按钮。

【讨论】:

谢谢你的回答,我还有一个小问题,如果我希望标记包含内容的自定义数据,而不是标题/图标。无论如何我可以扩展标记或markerOptions来为适配器添加自定义数据吗?(如果我的内容窗口包含一个评级栏,就像评级)我现在找到的解决方案是将标记和数据都放在喜欢的单独对象中一节课。 也许我应该编辑我的问题。 Marker.showInfoWindow() 仅适用于一个标记。我无法同时显示多个标记的信息窗口。 不是回答这个问题,而是真正有用的信息。它帮助了我。 +1【参考方案5】:

自定义标记图像

您可以将默认标记图像替换为自定义标记图像,通常称为图标。自定义图标始终设置为 BitmapDescriptor,并使用 BitmapDescriptorFactory 类中的四种方法之一进行定义。

fromAsset(字符串资产名称) 使用资产目录中的图像创建自定义标记。

fromBitmap(位图图像​​) 从位图图像创建自定义标记。

fromFile(字符串路径) 从指定路径的文件创建自定义图标。

fromResource (int resourceId) 使用现有资源创建自定义标记。 下面的 sn-p 创建一个带有自定义图标的标记。

 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)));

【讨论】:

【参考方案6】:

这个简单的代码可以在不需要点击事件的情况下显示标题:

googleMap.addMarker(new MarkerOptions()
        .position(latLng)
        .title(String title))
        .showInfoWindow();

【讨论】:

但是如果你有超过 1 个标记,这个方法 showInfoWindow() 只适用于最后一个【参考方案7】:

Google 推出了 IconGenerator 类,可以轻松添加自定义图标。

IconGenerator iconGenerator = new IconGenerator(mContext);
Bitmap bitmap = iconGenerator.makeIcon("Text Of Icon");
mMap.addMarker(new MarkerOptions()
                      .position(latlng)
                      .title("Location")
                      .icon(BitmapDescriptorFactory.fromBitmap(bitmap)));

【讨论】:

这个类来自哪个包或库?! 它说Cannot resolve symbol 'IconGenerator' for Android @CodeToLife - 这需要这里的库 - github.com/googlemaps/android-maps-utils【参考方案8】:

为什么不保留一个标记数组,然后在加载标记时,调用showInfoWindow() 遍历它们。可能不是最优雅的解决方案,但我认为它可以做到你所说的。

【讨论】:

您为一个标记调用 showInfoWindow() - 出现信息窗口。然后为第二个标记调用 showInfoWindow() - 窗口出现在第二个,第一个消失。这就是问题所在。【参考方案9】:

我通过使用具有以下详细信息的图片编辑器制作自己的标记解决了这个问题。制作需要一些时间,但它确实有效。

我使用了 Photoshop 和 53x110px 标记。

【讨论】:

您是在 Phoroshop 中为每个标记添加名称还是在 Android 中动态添加?

以上是关于带有自定义标记的 android Maps API v2的主要内容,如果未能解决你的问题,请参考以下文章

居中位图标记(Google Maps Android API v2)

标记之间的 Google Maps API 和自定义折线路线

Google Maps Android API v2,错误的标记位置

Google Maps API v3:在Firefox中未触发自定义标记的点击事件

React Native Maps - 自定义标记图像未在更高的 Android 版本中呈现

带有自定义标记的 Android 地图(标记上的文本)