谷歌地图中的自定义标记在android与矢量资产图标

Shu*_*ddh 53 android google-maps-markers google-maps-android-api-2

我们如何用矢量资产文件实现地图标记图标,google以这样的方式显示它,以编程方式:

地图

更新:

map.addMarker(new MarkerOptions()
    .position(latLng)
    .icon(BitmapDescriptorFactory.fromResource(R.drawable.your_vector_asset))
    .title(title);
Run Code Online (Sandbox Code Playgroud)

这在处理矢量资产时不起作用.提出问题的主要原因.上面代码的错误:

java.lang.IllegalArgumentException:无法解码图像.提供的图像必须是位图.

Leo*_*der 77

您可以使用此方法:

private BitmapDescriptor bitmapDescriptorFromVector(Context context, int vectorResId) {
        Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorResId);
        vectorDrawable.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
        Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);
        vectorDrawable.draw(canvas);
        return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Run Code Online (Sandbox Code Playgroud)

所以你的代码看起来像:

map.addMarker(new MarkerOptions()
                .position(latLng)
                .icon(bitmapDescriptorFromVector(getActivity(), R.drawable.your_vector_asset))
                .title(title);
Run Code Online (Sandbox Code Playgroud)

  • 在我的项目中使用它从矢量资产中获取标记。 (2认同)

Sid*_*rad 20

我一直在寻找完全相同的要求,看到这个问题让我开心,但与@Shuddh一样,我对给定的答案不满意.

为了简化我的故事,我使用以下代码来满足此要求:

private BitmapDescriptor bitmapDescriptorFromVector(Context context, @DrawableRes  int vectorDrawableResourceId) {
    Drawable background = ContextCompat.getDrawable(context, R.drawable.ic_map_pin_filled_blue_48dp);
    background.setBounds(0, 0, background.getIntrinsicWidth(), background.getIntrinsicHeight());
    Drawable vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId);
    vectorDrawable.setBounds(40, 20, vectorDrawable.getIntrinsicWidth() + 40, vectorDrawable.getIntrinsicHeight() + 20);
    Bitmap bitmap = Bitmap.createBitmap(background.getIntrinsicWidth(), background.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    background.draw(canvas);
    vectorDrawable.draw(canvas);
    return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Run Code Online (Sandbox Code Playgroud)

和一个用法示例:

.icon(bitmapDescriptorFromVector(this, R.drawable.ic_car_white_24dp));
Run Code Online (Sandbox Code Playgroud)

注意:您可能希望对矢量使用不同的边界,我的矢量大小为24dp,我使用了48dp的png图像(蓝色部分,也可以是矢量)作为背景.

更新:根据请求添加屏幕截图.

最终结果的屏幕截图

  • 我认为内部图像边界的计算应该不同(下面的 kotlin 实现):`val left = (background.intrinsicWidth - vectorDrawable.intrinsicWidth) / 2` `val top = (background.intrinsicHeight - vectorDrawable.intrinsicHeight) / 3` `vectorDrawable.setBounds(left, top, left + vectorDrawable.intrinsicWidth, top + vectorDrawable.intrinsicHeight)` (2认同)

M.Y*_*ran 8

如果有人正在寻找 kotlin 这里的方法适合你:

  private fun  bitmapDescriptorFromVector(vectorResId:Int):BitmapDescriptor {
            var vectorDrawable = ContextCompat.getDrawable(requireContext(), vectorResId);
            vectorDrawable!!.setBounds(0, 0, vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight());
            var bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(), vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
            var canvas =  Canvas(bitmap);
            vectorDrawable.draw(canvas);
            return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Run Code Online (Sandbox Code Playgroud)

上面的方法会将您的矢量图标转换为位图描述符

map.addMarker(new MarkerOptions()
                .position(latLng)
                .icon(bitmapDescriptorFromVector(getActivity(), R.drawable.your_vector_asset))
                .title(title)
Run Code Online (Sandbox Code Playgroud)

这是为你的地图设置标记的一个,感谢 Leo Droidcoder 的回答,只是我已将其转换为 kotlin


小智 8

这是 kotlin 爱好者的代码;)

private fun bitMapFromVector(vectorResID:Int):BitmapDescriptor {
    val vectorDrawable=ContextCompat.getDrawable(context!!,vectorResID)
    vectorDrawable!!.setBounds(0,0,vectorDrawable!!.intrinsicWidth,vectorDrawable.intrinsicHeight)
    val bitmap=Bitmap.createBitmap(vectorDrawable.intrinsicWidth,vectorDrawable.intrinsicHeight,Bitmap.Config.ARGB_8888)
    val canvas=Canvas(bitmap)
    vectorDrawable.draw(canvas)
    return BitmapDescriptorFactory.fromBitmap(bitmap)
}
Run Code Online (Sandbox Code Playgroud)

  • 您对这段代码有任何疑问吗?特别是“setBounds”部分? (2认同)

Shi*_*din 6

在 Kotlin 中:我使用下面的代码在标记上显示 SVG 图像。在这里,我没有使用背景颜色/SVG。

fun getBitmapDescriptorFromVector(context: Context, @DrawableRes vectorDrawableResourceId: Int): BitmapDescriptor? {

    val vectorDrawable = ContextCompat.getDrawable(context, vectorDrawableResourceId)
    val bitmap = Bitmap.createBitmap(vectorDrawable!!.intrinsicWidth, vectorDrawable.intrinsicHeight, Bitmap.Config.ARGB_8888)
    val canvas = Canvas(bitmap)
    vectorDrawable.setBounds(0, 0, canvas.width, canvas.height)
    vectorDrawable.draw(canvas)

    return BitmapDescriptorFactory.fromBitmap(bitmap)
}
Run Code Online (Sandbox Code Playgroud)

像这样使用:

googleMap?.addMarker(MarkerOptions().position(LatLng(it.latitude!!, it.longitude!!))
            .title(it.airLineDetails))?.setIcon(
            getBitmapDescriptorFromVector(requireContext(), R.drawable.ic_flight_blue))
Run Code Online (Sandbox Code Playgroud)

截屏:


pre*_*rak 5

可能有点晚了,但这对 Google Maps v2 非常有用:

public static BitmapDescriptor getBitmapFromVector(@NonNull Context context,
                                                   @DrawableRes int vectorResourceId,
                                                   @ColorInt int tintColor) {

    Drawable vectorDrawable = ResourcesCompat.getDrawable(
            context.getResources(), vectorResourceId, null);
    if (vectorDrawable == null) {
        Log.e(TAG, "Requested vector resource was not found");
        return BitmapDescriptorFactory.defaultMarker();
    }
    Bitmap bitmap = Bitmap.createBitmap(vectorDrawable.getIntrinsicWidth(),
            vectorDrawable.getIntrinsicHeight(), Bitmap.Config.ARGB_8888);
    Canvas canvas = new Canvas(bitmap);
    vectorDrawable.setBounds(0, 0, canvas.getWidth(), canvas.getHeight());
    DrawableCompat.setTint(vectorDrawable, tintColor);
    vectorDrawable.draw(canvas);
    return BitmapDescriptorFactory.fromBitmap(bitmap);
}
Run Code Online (Sandbox Code Playgroud)

初始化为:

locationMarkerIcon = LayoutUtils.getBitmapFromVector(ctx, R.drawable.ic_location_marker,
                ContextCompat.getColor(ctx, R.color.marker_color));
Run Code Online (Sandbox Code Playgroud)

用法:

googleMap.addMarker(MarkerOptions().icon(getMarkerIcon()).position(latLng));
Run Code Online (Sandbox Code Playgroud)

注意:getMarkerIcon()只返回初始化的非空locationMarkerIcon成员变量。

截屏:

在此处输入图片说明

  • @Shuddh 基本上我的矢量资源在我的屏幕截图中有点不同(基于我的项目),但据我所知,您最初的问题询问如何使用矢量资源作为标记图标,这就是静态方法的作用(以及还动态添加颜色)。 (2认同)