iOS中实现Google Maps集群图标点击切换的方法
解决Google Maps集群图标点击切换的问题
我帮你梳理下当前代码的问题点,然后给出具体的修改方案,让集群图标也能和单个标记点一样实现点击切换效果:
问题分析
- 你的
didRenderMarker代理方法只处理了**单个标记点(itemType)**的图标渲染,完全没处理集群标记点(clusterType)的图标生成与设置 - 点击集群时,你没有找到对应的集群Marker实例,也就无法更新它的选中状态和图标
具体修改步骤
1. 完善CustomMarker类,添加选中状态属性
首先确保你的自定义Marker类有统一的选中状态管理:
class CustomMarker: GMSMarker { enum MarkerType { case clusterType case itemType } var markerType: MarkerType = .itemType var markerCount: Int = 0 var isSelected: Bool = false // 新增:统一管理选中状态 var propertyListModal: PeropertyListModel? }
2. 新增集群图标生成方法
单独写一个生成集群图标的方法,支持选中/未选中两种状态:
// 生成集群标记视图(支持选中/未选中状态) private func createClusterMarkerView(isSelected: Bool, count: Int) -> UIView { // 根据选中状态切换底图,比如你需要准备clusterMarker和clusterMarker_selected两张图 let baseImage = isSelected ? UIImage(named: "clusterMarker_selected")! : UIImage(named: "clusterMarker")! let markerView = UIImageView(image: baseImage) // 添加集群数字标签 let countLabel = UILabel(frame: markerView.bounds) countLabel.text = String(count) countLabel.font = UIFont(name: "Futura-Medium", size: 12.0) ?? UIFont.systemFont(ofSize: 12) countLabel.textAlignment = .center countLabel.textColor = .black markerView.addSubview(countLabel) return markerView }
3. 修改didRenderMarker,补上集群标记的渲染逻辑
现在让这个方法同时处理单个标记和集群标记:
func renderer(_ renderer: GMUClusterRenderer, didRenderMarker marker: GMSMarker) { if let customMarker = marker as? CustomMarker { if customMarker.markerType == .itemType { // 原有单个标记的渲染逻辑保持不变 let propertyMarker = createMarkerView(isSelected: customMarker.isSelected) propertyMarker.markerPriceLabel.text = customMarker.propertyListModal?.propertyPrice marker.icon = propertyMarker.asImage() marker.groundAnchor = CGPoint(x: 0.5, y: 1) } else if customMarker.markerType == .clusterType { // 新增:渲染集群标记的图标 let clusterMarkerView = createClusterMarkerView(isSelected: customMarker.isSelected, count: customMarker.markerCount) marker.icon = clusterMarkerView.asImage() marker.groundAnchor = CGPoint(x: 0.5, y: 1) } } }
4. 修改集群点击代理方法,实现图标切换
在clusterManager(_:didTap:)里,找到当前点击的集群Marker,切换它的选中状态并更新图标:
func clusterManager(_ clusterManager: GMUClusterManager, didTap cluster: GMUCluster) -> Bool { let newCamera = GMSCameraPosition.camera(withTarget: cluster.position, zoom: propertyMapView.camera.zoom) let update = GMSCameraUpdate.setCamera(newCamera) propertyMapView.moveCamera(update) isClusterTapped = true clusterPropertyList = [] // 收集集群内的属性数据(原有逻辑不变) let properties = cluster.items properties.forEach({ (property) in if let propertyModal = property as? POIItem, propertyModal.propertyListModal != nil{ clusterPropertyList.append(propertyModal.propertyListModal!) } }) // 1. 取消之前选中的所有标记(包括单个和集群) if let previousMarker = propertyMapView.selectedMarker as? CustomMarker{ previousMarker.isSelected = false if previousMarker.markerType == .itemType { let propertyMarker = createMarkerView(isSelected: previousMarker.isSelected) propertyMarker.markerPriceLabel.text = previousMarker.propertyListModal?.propertyPrice previousMarker.icon = propertyMarker.asImage() } else if previousMarker.markerType == .clusterType { let clusterMarkerView = createClusterMarkerView(isSelected: previousMarker.isSelected, count: previousMarker.markerCount) previousMarker.icon = clusterMarkerView.asImage() } } // 2. 找到当前点击的集群对应的Marker var tappedClusterMarker: CustomMarker? for marker in propertyMapView.markers { if let customMarker = marker as? CustomMarker, customMarker.markerType == .clusterType, customMarker.position.latitude == cluster.position.latitude, customMarker.position.longitude == cluster.position.longitude, customMarker.markerCount == cluster.items.count { tappedClusterMarker = customMarker break } } // 3. 切换当前集群Marker的选中状态并更新图标 if let tappedMarker = tappedClusterMarker { tappedMarker.isSelected = !tappedMarker.isSelected let clusterMarkerView = createClusterMarkerView(isSelected: tappedMarker.isSelected, count: tappedMarker.markerCount) tappedMarker.icon = clusterMarkerView.asImage() propertyMapView.selectedMarker = tappedMarker } self.propertyListContainerForMap.isHidden = false self.propertyViewForMapCollectionView.reloadData() return true }
5. 初始化Marker时设置默认选中状态
在创建Marker的代理方法里,默认把选中状态设为false:
func renderer(_ renderer: GMUClusterRenderer, markerFor object: Any) -> GMSMarker? { let marker = CustomMarker() marker.isSelected = false // 初始化未选中状态 if let itemMarker = object as? GMUCluster { marker.markerType = .clusterType marker.markerCount = itemMarker.items.count } else if let itemMarker = object as? POIItem { marker.markerType = .itemType itemMarker.marker = marker marker.propertyListModal = itemMarker.propertyListModal } return marker }
修改关键点说明
- 给
CustomMarker添加统一的isSelected属性,让单个标记和集群标记的选中状态管理逻辑一致 - 新增集群图标生成方法,支持切换选中/未选中的底图
- 在渲染代理里补上集群标记的图标生成逻辑
- 在集群点击时,先处理之前选中的标记,再找到当前点击的集群Marker并更新状态和图标
内容的提问来源于stack exchange,提问作者Manish
相关产品推荐
相关产品推荐

