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

Flutter中实现地图CustomInfoWindow的显示与隐藏切换功能

解决Flutter自定义信息窗口点击Marker无法切换显示/隐藏的问题

我来帮你搞定这个问题!你当前的代码每次点击Marker都会直接调用addInfoWindow,完全没判断信息窗口当前是显示还是隐藏状态,所以自然没法实现再次点击隐藏的效果。我们只需要加个状态变量来跟踪窗口状态,再调整点击逻辑就行。

修改步骤:

  1. 添加状态变量:在你的State类里新增一个布尔变量,用来记录信息窗口是否可见
  2. 调整Marker点击逻辑:根据当前窗口状态,切换执行显示或隐藏操作
  3. 同步地图点击的状态更新:点击地图空白处隐藏窗口时,也要把状态变量重置为false

修改后的完整代码:

import 'package:clippy_flutter/triangle.dart';
import 'package:flutter/material.dart';
import 'package:google_maps_flutter/google_maps_flutter.dart';
import 'package:custom_info_window/custom_info_window.dart';

class CustomInfoWindowF extends StatefulWidget {
  @override
  _CustomInfoWindowExampleState createState() => _CustomInfoWindowExampleState();
}

class _CustomInfoWindowExampleState extends State<CustomInfoWindowF> {
  CustomInfoWindowController _customInfoWindowController = CustomInfoWindowController();
  final LatLng _latLng = LatLng(28.7041, 77.1025);
  final double _zoom = 15.0;
  bool _isInfoWindowVisible = false; // 新增:跟踪信息窗口显示状态

  @override
  void dispose() {
    _customInfoWindowController.dispose();
    super.dispose();
  }

  Set<Marker> _markers = {};

  @override
  Widget build(BuildContext context) {
    _markers.add(
      Marker(
        markerId: MarkerId("marker_id"),
        position: _latLng,
        onTap: () {
          setState(() {
            if (_isInfoWindowVisible) {
              // 如果窗口已显示,就隐藏
              _customInfoWindowController.hideInfoWindow();
              _isInfoWindowVisible = false;
            } else {
              // 如果窗口未显示,就添加并显示
              _customInfoWindowController.addInfoWindow(
                Column(
                  children: [
                    Expanded(
                      child: Container(
                        decoration: BoxDecoration(
                          color: Colors.blue,
                          borderRadius: BorderRadius.circular(4),
                        ),
                        child: Padding(
                          padding: const EdgeInsets.all(8.0),
                          child: Column(
                            children: [
                              Row(
                                mainAxisAlignment: MainAxisAlignment.center,
                                children: [
                                  Icon(
                                    Icons.account_circle,
                                    color: Colors.white,
                                    size: 30,
                                  ),
                                  SizedBox(
                                    width: 8.0,
                                  ),
                                  Text(
                                    "I am here",
                                    style: Theme.of(context).textTheme.headline6.copyWith(
                                          color: Colors.white,
                                        ),
                                  )
                                ],
                              ),
                            ],
                          ),
                        ),
                        width: double.infinity,
                        height: double.infinity,
                      ),
                    ),
                    Triangle.isosceles(
                      edge: Edge.BOTTOM,
                      child: Container(
                        color: Colors.blue,
                        width: 20.0,
                        height: 10.0,
                      ),
                    ),
                  ],
                ),
                _latLng,
              );
              _isInfoWindowVisible = true;
            }
          });
        },
      ),
    );

    return Scaffold(
      appBar: AppBar(
        title: Text('Custom Info Window Example'),
        backgroundColor: Colors.red,
      ),
      body: Stack(
        children: <Widget>[
          GoogleMap(
            onTap: (position) {
              _customInfoWindowController.hideInfoWindow();
              setState(() {
                _isInfoWindowVisible = false; // 修改:同步更新状态变量
              });
            },
            onCameraMove: (position) {
              _customInfoWindowController.onCameraMove();
            },
            onMapCreated: (GoogleMapController controller) async {
              _customInfoWindowController.googleMapController = controller;
            },
            markers: _markers,
            initialCameraPosition: CameraPosition(
              target: _latLng,
              zoom: _zoom,
            ),
          ),
          CustomInfoWindow(
            controller: _customInfoWindowController,
            height: 175,
            width: 250,
            offset: 50,
          ),
        ],
      ),
    );
  }
}

关键修改说明:

  • _isInfoWindowVisible变量:用来实时记录信息窗口的显示状态,初始值为false(窗口隐藏)
  • Marker的onTap逻辑:通过setState更新状态,判断当前窗口状态后执行对应的显示/隐藏操作
  • GoogleMap的onTap逻辑:点击地图空白处隐藏窗口时,同步把_isInfoWindowVisible设为false,确保下次点击Marker的逻辑判断准确

这样修改后,你点击Marker就能实现显示/隐藏自定义信息窗口的切换效果啦!

内容的提问来源于stack exchange,提问作者Omor Faruqe

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.30 12:49:07