Skip to content

GMUClusterRendererDelegate renderer not working for updating cluster image #567

@lightspect

Description

@lightspect

Environment details

  1. GMUClusterRendererDelegate
  2. OS: iOS 15
  3. Google Map 8.4 and Google Map Utils SDK 5.0

Steps to reproduce

  1. Download the iOS Utils Sample App
  2. Apply the renderer willRenderMarker function of the GMUClusterRendererDelegate into the ClusteringViewController

Code example

import GoogleMaps
import UIKit
import GoogleMapsUtils

/// Point of Interest Item which implements the GMUClusterItem protocol.
class POIItem: NSObject, GMUClusterItem {
  var position: CLLocationCoordinate2D
  var name: String!

  init(position: CLLocationCoordinate2D, name: String) {
    self.position = position
    self.name = name
  }
}

let kClusterItemCount = 10000
let kCameraLatitude = -33.8
let kCameraLongitude = 151.2

class ClusteringViewController: UIViewController, GMSMapViewDelegate, GMUClusterRendererDelegate {

  private var mapView: GMSMapView!
  private var clusterManager: GMUClusterManager!

  override func loadView() {
    let camera = GMSCameraPosition.camera(withLatitude: kCameraLatitude,
      longitude: kCameraLongitude, zoom: 10)
    mapView = GMSMapView.map(withFrame: CGRect.zero, camera: camera)
    self.view = mapView
  }

  override func viewDidLoad() {
    super.viewDidLoad()

    // Set up the cluster manager with default icon generator and renderer.
    let iconGenerator = GMUDefaultClusterIconGenerator()
    let algorithm = GMUNonHierarchicalDistanceBasedAlgorithm()
    let renderer = GMUDefaultClusterRenderer(mapView: mapView, clusterIconGenerator: iconGenerator)
    clusterManager = GMUClusterManager(map: mapView, algorithm: algorithm, renderer: renderer)
    
    // Register self to listen to GMSMapViewDelegate events.
    clusterManager.setMapDelegate(self)
    
    // Generate and add random items to the cluster manager.
    generateClusterItems()

    // Call cluster() after items have been added to perform the clustering and rendering on map.
    clusterManager.cluster()
  }

  // MARK: - GMUMapViewDelegate

  func mapView(_ mapView: GMSMapView, didTap marker: GMSMarker) -> Bool {
    mapView.animate(toLocation: marker.position)
    if let _ = marker.userData as? GMUCluster {
      mapView.animate(toZoom: mapView.camera.zoom + 1)
      NSLog("Did tap cluster")
      return true
    }
    NSLog("Did tap marker")
    return false
  }

  // MARK: - Private

  /// Randomly generates cluster items within some extent of the camera and adds them to the
  /// cluster manager.
  private func generateClusterItems() {
    let extent = 0.2
    for _ in 1...kClusterItemCount {
      let lat = kCameraLatitude + extent * randomScale()
      let lng = kCameraLongitude + extent * randomScale()
      let position = CLLocationCoordinate2D(latitude: lat, longitude: lng)
      let marker = GMSMarker(position: position)
      clusterManager.add(marker)
    }
  }

  /// Returns a random value between -1.0 and 1.0.
  private func randomScale() -> Double {
    return Double(arc4random()) / Double(UINT32_MAX) * 2.0 - 1.0
  }
    
    func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) {
        if let cluster = marker.userData as? GMUCluster {
            print("Current cluster size: \(cluster.count)")
            marker.icon = createClusterIcon(size: Int(cluster.count))
        }
    }
    
    func createClusterIcon(size: Int) -> UIImage {
       
       let clusterSize: CGFloat = 40
       let renderer = UIGraphicsImageRenderer(size: CGSize(width: clusterSize, height: clusterSize))
       
       let image = renderer.image { context in
           
               UIColor(red: 0.13, green: 0.59, blue: 0.95, alpha: 1.0).setFill()
               UIBezierPath(arcCenter: CGPoint(x: clusterSize / 2, y: clusterSize / 2), radius: clusterSize / 2, startAngle: 0, endAngle: .pi * 2, clockwise: true).fill()
           
           
           // Draw cluster count text
           let text = String(size)
           let attributes: [NSAttributedString.Key: Any] = [
               .font: UIFont.boldSystemFont(ofSize: 16),
               .foregroundColor: UIColor.white
           ]
           
           let textSize = text.size(withAttributes: attributes)
           let textPoint = CGPoint(
               x: (clusterSize - textSize.width) / 2,
               y: (clusterSize - textSize.height) / 2
           )
           text.draw(at: textPoint, withAttributes: attributes)
       }
       
       
       return image
   }
}

Expect Result

Cluster with icon blue circle and cluster size text to display. Print function run when icon display

Actual Result

Cluster still use the default cluster icon.

Metadata

Metadata

Assignees

No one assigned

    Labels

    triage meI really want to be triaged.type: bugError or flaw in code with unintended results or allowing sub-optimal usage patterns.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions