问题
I have a map I'm populating with a list of food trucks, and I'd like to implement a custom callout like the one shown below, when an annotation
is selected. Currently I have the standard annotation callout implemented with a title and subtitle.
I've done some reading and am guessing it'll require a custom .xib file, but I don't really know anything about this as I only started developing for iOS as a recently. How would I go about creating this custom popup, and how can I make it perform a navigation action when clicked?
Thanks!
回答1:
Seems like you need a custom pop up view, but you don't know how to create one.
Here a sample to create a pop view like the picture you post.
This is the code, ViewController.m:
#import "ViewController.h"
#import "AnnotationView.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
self.view.backgroundColor = [UIColor grayColor];
AnnotationView* popUp = [[AnnotationView alloc] initWithFrame:CGRectMake(50, 100, 200, 80)];
[self.view addSubview:popUp];
}
@end
AnnotationView.m:
#import "AnnotationView.h"
@interface AnnotationView ()
@property float bottomHeight;
@property float topHeight;
@property float cornerRadius;
@property float triangleWidth;
@property UIImageView* pictureView;
@property UILabel* lbTitle;
@property UILabel* lbInfo;
@end
@implementation AnnotationView
-(id)initWithFrame:(CGRect)frame{
_bottomHeight = 20;
_topHeight = frame.size.height-_bottomHeight;
_cornerRadius = 5;
_triangleWidth = 30;
self = [super initWithFrame:frame];
self.backgroundColor = [UIColor clearColor];
self.layer.cornerRadius = _cornerRadius;
self.layer.masksToBounds = YES;
_pictureView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, _topHeight, _topHeight)];
_pictureView.image = [UIImage imageNamed:@"test.png"];
_pictureView.layer.cornerRadius = _cornerRadius;
_pictureView.layer.masksToBounds = YES;
[self addSubview:_pictureView];
float insidePadding = 10;
float lbWidth = (frame.size.width-_topHeight-2*insidePadding);
_lbTitle = [[UILabel alloc] initWithFrame:CGRectMake(_topHeight+insidePadding, 0, lbWidth, _topHeight/2)];
_lbTitle.text = @"I'm title.";
[self addSubview:_lbTitle];
_lbInfo = [[UILabel alloc] initWithFrame:CGRectMake(_topHeight+insidePadding, _topHeight/2, lbWidth, _topHeight/2)];
_lbInfo.numberOfLines = 2;
_lbInfo.font = [UIFont systemFontOfSize:10];
_lbInfo.text = @"I'm content........I'm content........";
[self addSubview:_lbInfo];
return self;
}
-(void)drawRect:(CGRect)rect{
CGContextRef con = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(con, [UIColor whiteColor].CGColor);
UIBezierPath* roundRect = [UIBezierPath bezierPathWithRoundedRect:CGRectMake(0, 0, rect.size.width, _topHeight) cornerRadius:_cornerRadius];
CGContextAddPath(con, roundRect.CGPath);
CGContextFillPath(con);
CGContextMoveToPoint(con, (rect.size.width-_triangleWidth)/2, _topHeight);
CGContextAddLineToPoint(con,(rect.size.width+_triangleWidth)/2, _topHeight);
CGContextAddLineToPoint(con,rect.size.width/2, rect.size.height);
CGContextClosePath(con);
CGContextFillPath(con);
}
@end
Hope it can help you. Any more question just left it here.
回答2:
First to change the pin image you need to use viewForAnnotation
method of MKMapViewDelegate
and set the image
porperty of MKAnnotationView
also to show your own view set canShowCallout
property to false
.
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView? {
if (annotation.isKindOfClass(MKPointAnnotation.classForCoder())) {
var annotationView = mapView.dequeueReusableAnnotationViewWithIdentifier("AnnotationView")
if annotationView == nil {
annotationView = MKAnnotationView(annotation: annotation, reuseIdentifier: "AnnotationView")
}
else {
annotationView!.annotation = annotation
}
annotationView!.image = UIImage(named: "Marker")
annotationView!.canShowCallout = false
return annotationView
}
return nil
}
Now to show your own view use didSelectAnnotationView
method of MKMapViewDelegate
.
func mapView(mapView: MKMapView, didSelectAnnotationView view: MKAnnotationView) {
mapView.deselectAnnotation(view.annotation, animated: true)
let viewController = self.storyboard?.instantiateViewControllerWithIdentifier("AnnotationInfoViewController") as! AnnotationInfoViewController
//If you want to show view from XIB file you can create viewController instance like this
//let viewController = UIViewController()
//let myView = NSBundle.mainBundle().loadNibNamed("AnnotationInfoView", owner: self, options: nil)[0] as! AnnotationInfoView
//viewController.view = myView
//Pass the information that you want to show
viewController.data = passdata
//Set the viewController for popoverPresentationController
viewController.modalPresentationStyle = .Popover
viewController.preferredContentSize = CGSize(width: viewController.view.frame.size.width, height: 80)
viewController.popoverPresentationController!.delegate = self;
viewController.popoverPresentationController!.permittedArrowDirections = [.Up , .Down]
viewController.popoverPresentationController!.sourceView = view.superview!
viewController.popoverPresentationController!.sourceRect = view.frame
self.presentViewController(viewController, animated: true, completion: nil)
}
Now to show a popup view implement adaptivePresentationStyleForPresentationController
method of UIPopoverPresentationControllerDelegate
.
func adaptivePresentationStyleForPresentationController(controller: UIPresentationController) -> UIModalPresentationStyle {
return .None;
}
Note: Now if you want to handle the tap event for this popup, you can use UITapGestureRecognizer
.
来源:https://stackoverflow.com/questions/38734882/how-to-create-custom-pin-annotation-view