我想用自定义标记制作地图。在 API v2 中,我可以为标记设置图标、标题等。但我想在第一次开始时显示带有标记的标题。现在标题仅在我点击标记时显示。在 v1 中是叠加层,但在 v2 中我没有发现任何类似的东西。
编辑:
也许我不够清楚。类似Marker.showInfoWindow()
API 的东西只适用于一个标记。我无法同时显示所有标记的信息窗口。无论如何,我需要为所有标记显示标题,而无需等待用户点击它。
我想用自定义标记制作地图。在 API v2 中,我可以为标记设置图标、标题等。但我想在第一次开始时显示带有标记的标题。现在标题仅在我点击标记时显示。在 v1 中是叠加层,但在 v2 中我没有发现任何类似的东西。
编辑:
也许我不够清楚。类似Marker.showInfoWindow()
API 的东西只适用于一个标记。我无法同时显示所有标记的信息窗口。无论如何,我需要为所有标记显示标题,而无需等待用户点击它。
我也偶然发现了这个问题。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)
);
希望谷歌会添加适当的方法,以便我们可以轻松地做到这一点。该死,我真的很喜欢 V2 API 中的新地图旋转功能。
终于做到了。所以你要做的是有一个背景图像(在我的例子中,我只使用一个蓝色矩形)。像这样创建一个标记:
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) ;
}
感谢 Arun George: 以编程方式将文本添加到 android 中的图像
似乎您的问题终于在 Google I/O 会议上得到了解答。
看看http://googlemaps.github.io/android-maps-utils/
它有:
标记聚类——处理大量点的显示
热图 — 将大量点显示为热图
IconGenerator — 在你的标记上显示文本(见截图)
非常重要的是,它可以在任何线程上进行修改,因此处理许多标记变得轻而易举
我不确定您要实现哪个目标:在用户无需点击标记的情况下显示信息窗口,或者为信息窗口使用完全不同的视图(或两者兼而有之)。
我自己没有对此进行测试,但我猜Marker.showInfoWindow()可以解决问题(假设 Marker 的可见性已经是true
.
这里有两个选项,您应该参考GoogleMap.InfoWindowAdapter上的文档:
公共静态接口 GoogleMap.InfoWindowAdapter
为信息窗口的自定义呈现提供视图。
当需要显示标记的信息窗口时,将调用此提供程序上的方法,无论原因如何(用户手势或对 showInfoWindow() 的编程调用。由于任何时候只显示一个信息窗口,该提供者可以选择重用视图,也可以选择在每次方法调用时创建新视图。
在构建信息窗口时,此类中的方法按定义的顺序调用。要替换默认信息窗口,请使用您的自定义渲染覆盖 getInfoWindow(Marker)。要仅替换信息窗口内容,在默认信息窗口框架(标注气泡)内,保留 getInfoWindow(Marker) 的默认实现并覆盖 getInfoContents(Marker)。
基本上,您是否覆盖getInfoWindow()
或getInfoContents()
将取决于您是否只想自定义在标注气泡中看到的内容,或者您是否希望自定义整个信息窗口视图,包括标注气泡的替代方案。
一个警告:我相信当你覆盖这些方法时,它会简单地渲染视图当时的样子getInfoWindow()
或被getInfoContents()
调用的样子。我本人有兴趣尝试复制本地 Google Maps Android 应用程序的外观,该应用程序的地点名称旁边有一个小“方向”图标。我认为的问题之一(参见此处:https ://stackoverflow.com/a/13713536/129475 )是,如果您的视图中有类似按钮的东西,由于静态渲染,它的行为可能不像按钮。
自定义标记图像
您可以将默认标记图像替换为自定义标记图像,通常称为图标。自定义图标始终设置为 BitmapDescriptor,并使用 BitmapDescriptorFactory 类中的四种方法之一进行定义。
fromAsset(String assetName) 使用资产目录中的图像创建自定义标记。
fromBitmap(位图图像)从位图图像创建自定义标记。
fromFile (String path) 从指定路径的文件创建自定义图标。
fromResource (int resourceId) 使用现有资源创建自定义标记。下面的代码片段创建了一个带有自定义图标的标记。
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)));
这个简单的代码可以在不需要点击事件的情况下显示标题:
googleMap.addMarker(new MarkerOptions()
.position(latLng)
.title(String title))
.showInfoWindow();
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)));
为什么不保留一个标记数组,然后在加载标记时,遍历它们调用showInfoWindow()
. 可能不是最优雅的解决方案,但它可以满足您的想法。
我通过使用具有以下详细信息的图片编辑器制作自己的标记解决了这个问题。制作花了一些时间,但它确实有效。
我使用了 Photoshop 和 53x110px 的标记。