You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Flutter中如何用google_maps_flutter创建带侧边标签的地图标记?

解决google_maps_flutter标记旁常驻标题+点击弹窗需求

先说明为啥改map_style.json没用

你改的map_style.json里的elementType labels控制的是地图原生自带的标签(比如道路名、地名这类),完全管不到你自己添加的自定义Marker,所以不管怎么调都不会生效。

下面给你两个可行方案:

方案一:用LabelMarker(你提到的方案,调样式就能用)

虽然默认样式有点怪,但调整参数就能贴近谷歌地图效果,而且是官方支持的方式,步骤如下:

  • 把原来的Marker换成LabelMarker,直接通过label参数设置常驻标题,同时调整样式优化观感:
LabelMarker(
  markerId: MarkerId('marker_1'),
  position: LatLng(37.7749, -122.4194),
  label: '旧金山',
  // 自定义样式,让标签更顺眼
  textStyle: TextStyle(
    fontSize: 14,
    color: Colors.black,
    fontWeight: FontWeight.w500,
    backgroundColor: Colors.white.withOpacity(0.9),
    padding: EdgeInsets.symmetric(horizontal: 6, vertical: 2),
  ),
)
  • 实现点击弹窗:给GoogleMap加onMarkerTap事件,用状态变量控制InfoWindow的显示(可以用一个隐藏的Marker来承载InfoWindow):
bool _showInfoWindow = false;
LatLng _infoPos = LatLng(0,0);
String _infoContent = '';

// 地图组件部分
GoogleMap(
  onMarkerTap: (markerId) {
    if (markerId.value == 'marker_1') {
      _infoPos = LatLng(37.7749, -122.4194);
      _infoContent = '美国加利福尼亚州的港口城市';
      _showInfoWindow = true;
      setState(() {});
    }
  },
  onTap: (_) {
    // 点击空白处关闭弹窗
    _showInfoWindow = false;
    setState(() {});
  },
  markers: {
    LabelMarker(...), // 上面定义的带标签的标记
    if (_showInfoWindow)
      Marker(
        markerId: MarkerId('temp_info'),
        position: _infoPos,
        infoWindow: InfoWindow(title: '旧金山', snippet: _infoContent),
        visible: false, // 只显示弹窗,隐藏标记本身
      ),
  },
)

方案二:自定义带文字的Marker图标(完全控制样式)

如果LabelMarker怎么调都不满意,你可以自己生成带标题的图片当Marker图标,完全复刻谷歌地图的标签样式:

  • 写个方法生成带文字的图片:
Future<BitmapDescriptor> makeMarkerLabel(String label) async {
  final recorder = PictureRecorder();
  final canvas = Canvas(recorder);
  final textPainter = TextPainter(
    text: TextSpan(
      text: label,
      style: TextStyle(
        fontSize: 14,
        color: Colors.black87,
        fontWeight: FontWeight.w500,
      ),
    ),
    textDirection: TextDirection.ltr,
  );
  textPainter.layout();

  // 绘制白色背景框,带点圆角更自然
  final bgRect = Rect.fromLTWH(0, 0, textPainter.width + 10, textPainter.height + 6);
  canvas.drawRRect(
    RRect.fromRectAndRadius(bgRect, Radius.circular(3)),
    Paint()..color = Colors.white,
  );
  // 绘制文字
  textPainter.paint(canvas, Offset(5, 3));

  final image = await recorder.endRecording().toImage(
    bgRect.width.toInt(),
    bgRect.height.toInt(),
  );
  final byteData = await image.toByteData(format: ImageByteFormat.png);
  return BitmapDescriptor.fromBytes(byteData!.buffer.asUint8List());
}
  • 在页面初始化时生成图标,然后用普通Marker使用:
BitmapDescriptor? _customMarker;

@override
void initState() {
  super.initState();
  makeMarkerLabel('旧金山').then((icon) {
    setState(() => _customMarker = icon);
  });
}

// 地图里的Marker
if (_customMarker != null)
  Marker(
    markerId: MarkerId('marker_1'),
    position: LatLng(37.7749, -122.4194),
    icon: _customMarker!,
    infoWindow: InfoWindow(title: '旧金山', snippet: '详细信息'),
  )

这个方案能完全自定义标签的样式、背景、文字效果,和谷歌地图原生的标记标签几乎一样。

内容的提问来源于stack exchange,提问作者Vítor Fraporti Rosmann

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.14 03:21:04