Jetpack Compose中如何在Google地图标记旁显示文本
Jetpack Compose中如何在Google地图标记旁显示文本
你说得对,默认的Marker组件确实只会在点击时才弹出信息窗显示title和snippet,要让文本一直和标记图标“绑在一起”显示,得我们自己动手做个带文本的自定义标记图标才行。下面我给你捋捋怎么解决这个问题,都是纯本地代码,不用跳去别的网站找资源~
最直接的方案:合成带文本的自定义Bitmap作为标记图标
我们可以写一个工具方法,把你的标记图标和要显示的文本画在同一张Bitmap上,然后把这个合成后的Bitmap设置给Marker的icon参数。这样地图上显示的就是自带文本的标记了。
首先写生成自定义图标的工具方法(可以放在你的Compose所在的Activity,或者单独的工具类里):
fun Context.createMarkerIconWithText( iconResId: Int, text: String, textSize: Float = 14f, textColor: Int = Color.BLACK, padding: Int = 8 ): BitmapDescriptor { // 加载原始标记图标 val originalIcon = BitmapFactory.decodeResource(resources, iconResId) // 初始化绘制文本的画笔 val textPaint = Paint().apply { color = textColor textSize = textSize * resources.displayMetrics.scaledDensity isAntiAlias = true textAlign = Paint.Align.LEFT } // 计算文本的宽高 val textBounds = Rect() textPaint.getTextBounds(text, 0, text.length, textBounds) // 计算合成后Bitmap的尺寸:图标宽+文本宽+边距,高度取图标和文本中较高的那个 val totalWidth = originalIcon.width + textBounds.width() + padding * 2 val totalHeight = max(originalIcon.height, textBounds.height() + padding * 2) // 创建新的空白Bitmap val combinedBitmap = Bitmap.createBitmap(totalWidth, totalHeight, Bitmap.Config.ARGB_8888) val canvas = Canvas(combinedBitmap) // 绘制原始图标(垂直居中) val iconTop = (totalHeight - originalIcon.height) / 2f canvas.drawBitmap(originalIcon, 0f, iconTop, null) // 绘制文本(垂直居中,在图标右侧留边距) val textTop = (totalHeight + textBounds.height()) / 2f - textBounds.bottom canvas.drawText( text, originalIcon.width + padding.toFloat(), textTop, textPaint ) // 转成Marker可用的BitmapDescriptor返回 return BitmapDescriptorFactory.fromBitmap(combinedBitmap) }
然后在你的Compose地图代码里,调用这个方法生成自定义图标:
GoogleMap( googleMapOptionsFactory = { GoogleMapOptions().mapId(MapDefaults.mapId) }, cameraPositionState = cameraPositionState, properties = style.mapProperties, uiSettings = style.mapUiSettings, onMapClick = onMapClick, onMapLoaded = onMapLoaded, ) { val context = LocalContext.current // 用remember包裹,避免每次重组都重新生成Bitmap,优化性能 val customMarkerIcon = remember { context.createMarkerIconWithText( iconResId = R.drawable.your_icon, text = "Text beside the icon" ) } Marker( state = MarkerState(position = LatLng(latitude, longitude)), icon = customMarkerIcon ) }
小提示
- 工具方法里的
textSize、textColor、padding这些参数,你可以完全根据自己的UI需求调整 - 用
remember包裹customMarkerIcon是为了避免Compose重组时重复生成Bitmap,能省不少性能
备选思路(不推荐):强制显示信息窗
还有一种方法是通过InfoWindowAdapter自定义信息窗内容,然后主动调用marker.showInfoWindow()让它一直显示,但这种方法有个小问题:信息窗是悬浮在地图上的独立视图,和标记图标不是完全绑定的,缩放地图时可能会有偏移,体验不如第一种方法流畅,所以只作为备选提一下~
备注:内容来源于stack exchange,提问作者Pawandeep Singh




