iOS 11 - map cluster annotation icon size behaviour - ios

Is there any way to resize the large annotation as same as the left ones.It is iOS11 behaviour and I want the unique size for all annotations like before.
Thanks in advance

This is what I have done for my project
In delegate method
- (MKAnnotationView *) mapView:(MKMapView *)mapView1 viewForAnnotation:(id <MKAnnotation>) annotation
1) create the annotation view
MKAnnotationView *annView = [[MKAnnotationView alloc] initWithAnnotation:currentAnnotation reuseIdentifier:#"Cluster"];
2) set the frame and other properties
[annView setFrame:CGRectMake(0, 0,100,100)]; //(Important)
annView.canShowCallout = YES;
[annView setCenterOffset:CGPointMake(0, -18)];
3) add image view as sub view with same frame size
UIImageView *homeImage = [[UIImageView alloc] initWithImage:[UIImage cachedImage:#"GroupPin"]];
[homeImage setFrame:CGRectMake(0, 0,100,100)]; //(Important)
[annView addSubview:homeImage];
return annView;
and you are done.

Related

MKAnnotationView Subviews

Currently, I am having an issue with my project in implementing a custom MKAnnotationView that has multiple custom UIImageViews. So these custom UIImageViews have a clear button on top of them to not have to add gesture recognizers.
As you can see, it would be beneficial to actually tap the MKAnnotationView subviews and have some action happen.
I implemented a protocol for the MKAnnotationView where each image subview within the MKAnnotationView makes a callback to the controller that is the owner of the MKMapView... Heres the code...
PHProfileImageView *image = [[PHProfileImageView alloc] initWithFrame:CGRectMake(newX - radius / 5.0f, newY - radius / 5.0f, width, height)];
[image setFile:[object objectForKey:kPHEventPictureKey]];
[image.layer setCornerRadius:image.frame.size.height/2];
[image.layer setBorderColor:[[UIColor whiteColor] CGColor]];
[image.layer setBorderWidth:2.0f];
[image.layer setMasksToBounds:YES];
[image.profileButton setTag:i];
[image.profileButton addTarget:self action:#selector(didTapEvent:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:image];
- (void)didTapEvent:(UIButton *)button
{
NSLog(#"%#", [self.pins objectAtIndex:button.tag]);
if (self.delegate && [self.delegate respondsToSelector:#selector(didTapEvent:)]) {
[self.delegate JSClusterAnnotationView:self didTapEvent:[self.pins objectAtIndex:button.tag]];
}
}
So as you can see, I already attempt to log the result of the tapped image but nothing :(. Is the way I'm implementing this not the way to go? Am I supposed to have CAShapeLayers or something? Not really sure at this point. Anyone got any ideas?
Edit
Im thinking that I might have to implement a custom callout view. Since a callout view actually adds buttons to its view and can respond to touch events... Not totally sure though because callouts are only shown once the annotation view is tapped. And in this case, the ACTUAL annotation view is the middle label
So I resized the mkannotationview's frame to a much larger frame and apparently all the subviews are actually not within the MKAnnotationView's bounds, so the subviews aren't actually being tapped. Now that Im thinking about this solution, it probably wasn't the best solution.
If anyone has any suggestions rather than adding subviews to a MKAnnotationView to create the view I currently have, that would be great!
For the Custom AnnotationView with Clickable Buttons, you have to create custom AnnotationView SubClass in the Project. For that create a new file.
And add these two methods to the implementation file.
- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event
{
UIView* hitView = [super hitTest:point withEvent:event];
if (hitView != nil)
{
[self.superview bringSubviewToFront:self];
}
return hitView;
}
- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event
{
CGRect rect = self.bounds;
BOOL isInside = CGRectContainsPoint(rect, point);
if(!isInside)
{
for (UIView *view in self.subviews)
{
isInside = CGRectContainsPoint(view.frame, point);
if(isInside)
break;
}
}
return isInside;
}
Then go to the ViewController.m file again and modify the viewDidLoad method as this.
- (void)viewDidLoad {
[super viewDidLoad];
self.mapKit.delegate = self;
//Set Default location to zoom
CLLocationCoordinate2D noLocation = CLLocationCoordinate2DMake(51.900708, -2.083160); //Create the CLLocation from user cordinates
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(noLocation, 50000, 50000); //Set zooming level
MKCoordinateRegion adjustedRegion = [self.mapKit regionThatFits:viewRegion]; //add location to map
[self.mapKit setRegion:adjustedRegion animated:YES]; // create animation zooming
// Place Annotation Point
MKPointAnnotation *annotation1 = [[MKPointAnnotation alloc] init]; //Setting Sample location Annotation
[annotation1 setCoordinate:CLLocationCoordinate2DMake(51.900708, -2.083160)]; //Add cordinates
[self.mapKit addAnnotation:annotation1];
}
Now add that custom View to the ViewController.xib.
Now create this delegate method as below.
#pragma mark : MKMapKit Delegate
-(MKAnnotationView *)mapView:(MKMapView *)mV viewForAnnotation:(id <MKAnnotation>)annotation
{
AnnotationView *pinView = nil; //create MKAnnotationView Property
static NSString *defaultPinID = #"com.invasivecode.pin"; //Get the ID to change the pin
pinView = (AnnotationView *)[self.mapKit dequeueReusableAnnotationViewWithIdentifier:defaultPinID]; //Setting custom MKAnnotationView to the ID
if ( pinView == nil )
pinView = [[AnnotationView alloc]
initWithAnnotation:annotation reuseIdentifier:defaultPinID]; // init pinView with ID
[pinView addSubview:self.customView];
addSubview:self.customView.center = CGPointMake(self.customView.bounds.size.width*0.1f, -self.customView.bounds.size.height*0.5f);
pinView.image = [UIImage imageNamed:#"Pin"]; //Set the image to pinView
return pinView;
}
I also got this answer few months ago from someone posted on Stackoverflow. I modified it to my project as I want. Hope this will do your work.

MKAnnotationView custom button image

I am trying to use a custom image on my MKAnnotationView when I use the following code I get no image on my annotation. I have checked in debug to ensure the image is being properly loaded into the UIImage.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation {
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"String"];
if(!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"String"];
UIButton *directionButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *directionIcon = [UIImage imageNamed:#"IconDirections"];
[directionButton setImage:directionIcon forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = directionButton;
}
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
return annotationView;
}
There are two main issues:
The frame of the custom callout button is not set making it essentially invisible.
An MKAnnotationView is being created but its image property (the image of the annotation itself -- not the callout button's) is not set. This makes the whole annotation invisible.
For issue 1, set the button's frame to some appropriate value. For example:
UIImage *directionIcon = [UIImage imageNamed:#"IconDirections"];
directionButton.frame =
CGRectMake(0, 0, directionIcon.size.width, directionIcon.size.height);
For issue 2, set the annotation view's image (or create an MKPinAnnotationView instead):
annotationView.image = [UIImage imageNamed:#"SomeIcon"];
Additionally, you should handle view re-use correctly by updating the annotation property.
Complete example:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"String"];
if(!annotationView) {
annotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"String"];
annotationView.image = [UIImage imageNamed:#"SomeIcon"];
UIButton *directionButton = [UIButton buttonWithType:UIButtonTypeCustom];
UIImage *directionIcon = [UIImage imageNamed:#"IconDirections"];
directionButton.frame =
CGRectMake(0, 0, directionIcon.size.width, directionIcon.size.height);
[directionButton setImage:directionIcon forState:UIControlStateNormal];
annotationView.rightCalloutAccessoryView = directionButton;
annotationView.enabled = YES;
annotationView.canShowCallout = YES;
}
else {
//update annotation to current if re-using a view
annotationView.annotation = annotation;
}
return annotationView;
}
In order for the callout to be shown, the annotation must be selected. To do this programmatically, call:
[mapView selectAnnotation:annotation animated:YES];
where annotation is the specific MKAnnotation for which you want a callout displayed.
You'll almost certainly want to put this in - (void)mapView:(MKMapView *)mapView didAddAnnotationViews:(NSArray *)views.
There are a few caveats to consider, so here are two other posts that have some great answers and relevant discussions:
How to trigger MKAnnotationView's callout view without touching the pin?
Wanted: How to reliably, consistently select an MKMapView annotation

Put user profile photo to map pin in ios dynamically

I want to show all user photos to map in iOS.Here,all user photos are coming from server through web service.
let me attach screen show what I want to achieve to get better idea.
e.g image of pin:
So I want to create custom pin like above for all users to show in map of iphone application.
can any one redirect me to achieve above task in ios.
Thanks in advance.
I am pasting a code from one of my project. but you will get main idea. i am dealing with bunch or different stores so i add tag on every annotation. also i am using SDWebImage library to load remote images dynamically.
the green pin is mapPin and circle image is dynamically loaded from server
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id )annotation {
if ([annotation isKindOfClass:[MKUserLocation class]])
return nil;
MKAnnotationView *aView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"mapPin"];
if(aView){
aView.annotation = annotation;
} else {
aView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"mapPin"];
ESMapViewAnnotation *newAnnotation=(ESMapViewAnnotation *)annotation;
ZBStore *s=(ZBStore *)[dataArray objectAtIndex:newAnnotation.tag];
NSString *iURL=s.Icon;
UIImageView *imageView = [[UIImageView alloc] init];
[imageView setImageWithURL:[NSURL URLWithString:iURL]
placeholderImage:[UIImage imageNamed:#"Question.jpg"]];
imageView.layer.borderWidth=1;
imageView.layer.borderColor=[[UIColor whiteColor]CGColor];
imageView.backgroundColor=s.BColor;
CGRect f= CGRectMake(2,2,46,43);
[imageView setFrame:f];
imageView.layer.cornerRadius=22.0;
imageView.layer.masksToBounds=YES;
aView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
[aView addSubview:imageView];
aView.enabled = YES;
aView.canShowCallout = YES;
aView.image = [UIImage imageNamed:#"gPin2.png"];//here we use a nice image instead of the default pins
}
return aView;
//return nil;
}

Map Annotation Adding Image

Below, I have created an Annotation for my map which works perfectly and shows up with the title and subtitle as it should.
But I wish to add a small image to the left of the annotation but can't figure out what I need to do to the below code to make it work.
// Annotation
CLLocationCoordinate2D poseLocation;
poseLocation.latitude = POSE_LATITUDE;
poseLocation.longitude = POSE_LONGITUDE;
Annotation *myAnnotation = [[Annotation alloc] init];
myAnnotation.coordinate = poseLocation;
myAnnotation.title = #"Pose Beauty Salon";
myAnnotation.subtitle = #"100, Moneyhaw Road";
[self.myMapView addAnnotation:myAnnotation];
You will need to set the delegate of your myMapView first and implement the viewForAnnotation delegate method.
There you will return MKAnnotationView instance which has a property leftCalloutAccessoryView:
The view to display on the left side of the standard callout bubble.
The default value of this property is nil. The left callout view is
typically used to display information about the annotation or to link
to custom information provided by your application. The height of your
view should be 32 pixels or less.
In the leftCalloutAccessoryView, you can assign your image there. For example:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[self.myMapView dequeueReusableAnnotationViewWithIdentifier:#"annotation"];
if (annotationView == nil) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"annotation"];
UIImageView *imageView = //initialize your image view here
annotationView.leftCalloutAccessoryView = imageView;
}
annotationView.annotation = annotation;
return annotationView;
}
PS: Apparently you have asked similar question before here: Add image to the left of my annotations. I am not sure you need to post another question. Please try to implement this first.
-(MKAnnotationView *) mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation{
MKPinAnnotationView *MyPin=[[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"current"];
myImage = [UIImage imageNamed:imagename];
CGRect cropRect = CGRectMake(0.0, 0.0,35.0, 35.0);
myImageView = [[UIImageView alloc] initWithFrame:cropRect];
myImageView.clipsToBounds = YES;
myImageView.image = myImage;
MyPin.leftCalloutAccessoryView =myImageView;
MyPin.highlighted=YES;
MyPin.canShowCallout=YES;
return MyPin;
}
It works for me , try this one

iOS - Set Detail Disclosure Button on MKAnnotationView

I have the following method in my MapViewController:
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation {
MKAnnotationView *annotationView = [mapView dequeueReusableAnnotationViewWithIdentifier:#"MapVC"];
if (!annotationView) {
annotationView = [[MKPinAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:#"MapVC"];
annotationView.canShowCallout = YES;
annotationView.leftCalloutAccessoryView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 30, 30)];
annotationView.rightCalloutAccessoryView = [UIButton buttonWithType:UIButtonTypeDetailDisclosure];
// could put a rightCalloutAccessoryView here
} else {
annotationView.annotation = annotation;
[(UIImageView *)annotationView.leftCalloutAccessoryView setImage:nil];
}
return annotationView;
}
I believe it's properly set up, but when my map shows my annotations with title and subtitle properly, but they don't show the detail disclosure button, am I missing something?
Another thing is that when debugging this method is never called, yet the annotation view shows up with title and subtitle.
Most likely the map view's delegate is not set.
If the delegate is not set or if you don't implement the viewForAnnotation method, the map view will create a default annotation view which is a red pin with a callout containing only the title and subtitle (unless the title is blank in which case you will get a pin but no callout).
Either connect the map view's delegate outlet to File's Owner or in code add this (eg. in viewDidLoad before the annotation is added):
mapView.delegate = self;
Also, if you're not using ARC, add autorelease to the alloc lines to avoid a memory leak.

Resources