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

iOS中实现Google Maps集群图标点击切换的方法

解决Google Maps集群图标点击切换的问题

我帮你梳理下当前代码的问题点,然后给出具体的修改方案,让集群图标也能和单个标记点一样实现点击切换效果:

问题分析

  1. 你的didRenderMarker代理方法只处理了**单个标记点(itemType)**的图标渲染,完全没处理集群标记点(clusterType)的图标生成与设置
  2. 点击集群时,你没有找到对应的集群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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.11 08:07:07