Custom Token Using GMUClusterManager

I want to show a custom token using GMUClusterManager . I followed all the steps for clustering tokens here .

but there is blue and red color. enter image description here

But when I enlarge this map, it only displays a red marker, but I do not want this.

there is an instance method where I implemented my logic but did not use.

  - (instancetype)initWithMapView:(GMSMapView *)mapView clusterIconGenerator:(id<GMUClusterIconGenerator>)iconGenerator { if ((self = [super init])) { GMSMarker *marker= [GMSMarker markerWithPosition:CLLocationCoordinate2DMake(24.0, 75.30)]; UIView *customMarker =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 40)]; customMarker.backgroundColor = [UIColor blueColor]; marker.iconView = [self EmployeeMarker:0] ; marker.appearAnimation = kGMSMarkerAnimationPop; marker.map = mapView; } return self; } -(UIView *)EmployeeMarker:(int)labelTextInt{ UIView *customMarker =[[UIView alloc] initWithFrame:CGRectMake(0, 0, 63, 40)]; UIImageView *imgViewCustomMarker = [[UIImageView alloc]initWithFrame:CGRectMake(0, 15, 24, 25)]; imgViewCustomMarker.image = [UIImage imageNamed:@"iconMapUser.png"]; [customMarker addSubview:imgViewCustomMarker]; UIView *viewRatingCustom = [[UIView alloc] initWithFrame:CGRectMake(15, 0, 40, 15)]; viewRatingCustom.backgroundColor = [UIColor colorWithRed:192.0/255.0 green:192.0/255.0 blue:192.0/255.0 alpha:1.0]; UILabel *lblRatingEmployees = [[UILabel alloc] initWithFrame:CGRectMake(8, 1, 17,8)]; lblRatingEmployees.textColor = [UIColor colorWithRed:0.00/255.0 green:100.0/255.0 blue:150.0/255.0 alpha:1.0]; lblRatingEmployees.text = @"1"; lblRatingEmployees.font = [UIFont fontWithName:@"Helvetica-Bold" size:10]; [lblRatingEmployees sizeToFit]; [viewRatingCustom addSubview:lblRatingEmployees]; UIImageView *imageViewStar = [[UIImageView alloc] initWithFrame:CGRectMake(25, 3, 10, 8)]; imageViewStar.image = [UIImage imageNamed:@"iconBlueStar.png"]; [viewRatingCustom addSubview:imageViewStar]; [customMarker addSubview:viewRatingCustom]; return customMarker; } 

I used this method to display the possible number of markers, red by default.

 id<GMUClusterAlgorithm> algorithm = [[GMUNonHierarchicalDistanceBasedAlgorithm alloc] init]; id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init]; id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator]; _clusterManager = [[GMUClusterManager alloc] initWithMap:_mapView algorithm:algorithm renderer:renderer]; // Generate and add random items to the cluster manager. // [self generateClusterItems]; for (int i = 0; i<latitudeArray.count; i++) { id<GMUClusterItem> item = [[POIItem alloc]initWithPosition:CLLocationCoordinate2DMake([[latitudeArray objectAtIndex:i]doubleValue], [[longitudeArray objectAtIndex:i]doubleValue]) name:@"Name"]; [_clusterManager addItem:item]; } 

Adde delegates as well as the cluster method.

  [_clusterManager cluster]; [_clusterManager setDelegate:self mapDelegate:self]; 

Therefore, please help me add a custom marker instead of the red one, which is the default.

+8
ios objective-c google-maps markerclusterer
source share
5 answers

You need to create your own class that conforms to the GMUClusterIconGenerator protocol:

File CustomClusterIconGenerator.h

 @interface CustomClusterIconGenerator : NSObject <GMUClusterIconGenerator> @end 

File CustomClusterIconGenerator.m

 @implementation CustomClusterIconGenerator - (UIImage *)iconForSize:(NSUInteger)size { // Return custom icon for cluster return [UIImage imageNamed:@"Your Custom Cluster Image"]; } - (UIImage *)iconForMarker { // Return custom icon for pin return [UIImage imageNamed:@"Your Custom Marker Image"]; } - (CGPoint)markerIconGroundAnchor { // If your marker icon center shifted, return custom value for anchor return CGPointMake(0, 0); } - (CGPoint)clusterIconGroundAnchor { // If your cluster icon center shifted, return custom value for anchor return CGPointMake(0, 0); } @end 

and then instead

 id<GMUClusterIconGenerator> iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init]; 

using

 CustomClusterIconGenerator *iconGenerator = [[GMUDefaultClusterIconGenerator alloc] init]; 

Here is an example from my project: enter image description here

+7
source share

You can check the tutorial - Marker clustering using the Google Utility SDK library (Google-Maps-iOS-Utils) , this is a real example of what you want to implement in your application. In addition, blog ) has code examples that you can try. Finally, a problem appeared on github about How to configure individual tokens added to the cluster manager? , this can help you understand how to configure markers in GMUClusterManager. Hope this helps.

+2
source share

Starting with version 1.1.0, new features have been added for easy marker setup ( read more ).

You can add GMUClusterRendererDelegate and GMUDefaultClusterRenderer.h and add the method - (void)renderer:(id<GMUClusterRenderer>)renderer willRenderMarker:(GMSMarker *)marker;

There you can configure your markers and clusters. For example:

 - (void)renderer:(id<GMUClusterRenderer>)renderer willRenderMarker:(GMSMarker *)marker{ if ([marker.userData conformsToProtocol:@protocol(GMUCluster)]) { marker.icon=[UIImage imageNamed:@"custom_cluster_image.png"]; }else if ([marker.userData conformsToProtocol:@protocol(GMUClusterItem)]) { marker.icon=[UIImage imageNamed:@"custom_marker_image.png"]; } } 

Remember to set the delegate correctly:

 id<GMUClusterRenderer> renderer = [[GMUDefaultClusterRenderer alloc] initWithMapView:_mapView clusterIconGenerator:iconGenerator]; ((GMUDefaultClusterRenderer *)renderer).delegate=self; 
+2
source share

In Swift 4.2 :

add this extension to your controller and make sure your controller is a delegate to GMUClusterRendererDelegate :

willRenderMarker will call every time a marker is displayed (both a cluster marker and clusterItemMarker so you can check it with a simple if). Therefore, you can change its icon, etc., before showing it to the user.

 extension YourController: GMUClusterRendererDelegate { func renderer(_ renderer: GMUClusterRenderer, willRenderMarker marker: GMSMarker) { // if your marker is pointy you can change groundAnchor marker.groundAnchor = CGPoint(x: 0.5, y: 1) if let markerData = (marker.userData as? PersonMarker) { let icon = markerData.imageURL marker.iconView = CustomMarkerView(forUrl: url) } } } 

And the PersonMarker of your marker class, a subclass of NSObject and GMUClusterItem : (you can use the default class from GMUClusterItem , but if you need any other properties that you can inherit from)

 class PersonMarker: NSObject, GMUClusterItem { var position: CLLocationCoordinate2D var imageURL : String? var name: String? var userdId: String? var lastSeen: String? init(position: CLLocationCoordinate2D, url: String?, name: String?, userId: String?, lastSeen: String?) { self.position = position self.imageURL = url self.name = name self.userdId = userId self.lastSeen = lastSeen } } 

You can add PersonMarker to your GMUClusterManager as follows:

 let position = CLLocationCoordinate2D(latitude: item.latitude!, longitude: item.longitute!) let person = PersonMarker(position: position, url: item.user?.avaterUrl, name: item.user?.name, userId: item.user?.userId, lastSeen: item.lastUpdate) clusterManager.add(person) 
+2
source share

You need a custom class that implements GMUClusterIconGenerator with a developed func icon(forSize size: UInt) β†’ UIImage! method that returns a UIImage for your cluster.

I suggest creating a view and functionality to add to it a designed label with a cluster heading, and then create a UIImage from your UIView .

Then you can create your own cluster generator as follows:

 let iconGenerator = ClusterIconGenerator() 

 class ClusterIconGenerator: NSObject, GMUClusterIconGenerator { private struct IconSize { private let initialFontSize: CGFloat = 12 private let fontMultiplier: CGFloat = 0.1 private let initialSize: CGFloat = 25 private let sizeMultiplier: CGFloat = 0.18 /** Rounded cluster sizes (like 10+, 20+, etc.) */ private let sizes = [10,20,50,100,200,500,1000] let size: UInt /** Returns scale level based on size index in 'sizes'. Returns '1' if size doesn't have rounded representation */ private var scaleLevel: UInt { if let index = sizes.lastIndex(where: { $0 <= size }) { return UInt(index) + 2 } else { return 1 } } /** Returns designed title from cluster size */ var designedTitle: String { if let size = sizes.last(where: { $0 <= size }) { return "\(size)+" } else { return "\(size)" } } /** Returns initial font size multiplied by recursively created multiplier */ var designedFontSize: CGFloat { let multiplier: CGFloat = (1...scaleLevel).reduce(1) { n,_ in n + n * fontMultiplier } return initialFontSize * multiplier } /** Returns initial 'CGSize' multiplied by recursively created multiplier */ var designedSize: CGSize { let multiplier: CGFloat = (1...scaleLevel).reduce(1) { n,_ in n + n * sizeMultiplier } return CGSize(width: initialSize * multiplier, height: initialSize * multiplier) } } /** Returns image based on current cluster size */ func icon(forSize size: UInt) -> UIImage! { let iconSize = IconSize(size: size) let frame = CGRect(origin: .zero, size: iconSize.designedSize) let view = UIView(frame: frame) view.layer.cornerRadius = iconSize.designedSize.height / 2 view.backgroundColor = .green let label = UILabel(frame: frame) label.textAlignment = .center label.textColor = .white label.text = iconSize.designedTitle view.addSubview(label) return view.asImage } } extension UIView { var asImage: UIImage { let renderer = UIGraphicsImageRenderer(bounds: bounds) return renderer.image { rendererContext in layer.render(in: rendererContext.cgContext) } } } 
0
source share

All Articles