Как добавить пользовательский вид на карте Аннотации Выноски
Вот мой код. Я хочу добавить собственное собственное представление выноски вместо iOS по умолчанию. Я знаю, что есть только левая выноска и правый вид выноски, но мне нужно добавить тип всплывающей подсказки с моим собственным фоном и меткой.
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
{
MKAnnotationView *userAnnotationView = nil;
if ([annotation isKindOfClass:MKUserLocation.class])
{
userAnnotationView = (MKAnnotationView *)[mapView dequeueReusableAnnotationViewWithIdentifier:@"UserLocation"];
if (userAnnotationView == nil) {
userAnnotationView = [[MKAnnotationView alloc] initWithAnnotation:annotation reuseIdentifier:@"UserLocation"];
}
else
userAnnotationView.annotation = annotation;
userAnnotationView.enabled = YES;
userAnnotationView.canShowCallout = YES;
userAnnotationView.image = [UIImage imageNamed:@"map_pin.png"];
UIView *view = [[UIView alloc]initWithFrame:CGRectMake(0,0,141,108)];
view.backgroundColor = [UIColor clearColor];
UIImageView *imgView = [[UIImageView alloc]initWithImage:[UIImage imageNamed:@"toltip.png"]];
[view addSubview:imgView];
userAnnotationView.leftCalloutAccessoryView = view;
return userAnnotationView;
}
}
![Image for reference]()
Ответы
Ответ 1
У меня была такая же проблема, и я закончил делать следующее:
Когда я получаю обратный вызов делегата mapView
-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
(это время, когда я хочу показать свой пользовательский CalloutView)
Я использую представление, полученное как параметр * (MKAnnotationView) view (который представляет собой представление вывода), и просто добавляйте мой пользовательский вид в этот вывод с помощью
[view addSubview:customView];
Он добавит ваш пользовательский вид поверх этого представления булавки, поэтому, если мы хотим, чтобы он был выше PIN-кода, мы должны изменить собственное свойство центра просмотра следующим образом:
CGRect customViewRect = customView.frame;
CGRect rect = CGRectMake(-customViewRect.size.width/2, -customViewRect.size.height-7, customViewRect.size.width, customViewRect.size.height);
customView.frame = rect;
[view addSubview:customView];
В моем случае это выглядит как
![enter image description here]()
! ПРИМЕЧАНИЕ:
Существует одно предостережение, которое, однако, может быть легко исправлено, ваш пользовательский вид будет игнорировать события касания, из-за mapView, работающего с касаниями по-разному. Здесь быстрое исправление:
1) Подкласс MKAnnotationView (или MKPinAnnotationView зависит от того, что вам нужно)
2) в вашем делегате mapView
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id <MKAnnotation>)annotation
используйте свой подкласс вместо MKAnnotationView/MKPinAnnotationView
3) в вашем подклассе .m файл переопределяет два метода следующим образом:
- (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;
}
Все сделано!
Ответ 2
Я создал библиотеку для отображения пользовательских выносок.
DXCustomCallout-ObjC
Вы можете передать любое настраиваемое представление для выноски!
Он также поддерживает события для UIControls.
![Custom Callout]()
Ответ 3
К лучшему ответу выше в Swift
Это может сэкономить несколько минут, чтобы переписать сам.
! Примечание:
Существует одно предостережение, которое, однако, может быть легко исправлено, ваше пользовательское представление будет игнорировать события касания, поскольку mapView работает с касаниями по-разному. Вот быстрое решение:
1) Подкласс MKAnnotationView (или MKPinAnnotationView зависит от того, что вам нужно)
2) в делегате mapView
func mapView(mapView: MKMapView, viewForAnnotation annotation: MKAnnotation) -> MKAnnotationView?
используйте свой подкласс вместо MKAnnotationView/MKPinAnnotationView
3) в вашем подклассе .m файл переопределяет два метода следующим образом:
override func hitTest(point: CGPoint, withEvent event: UIEvent?) -> UIView? {
let hitView = super.hitTest(point, withEvent: event)
if (hitView != nil)
{
self.superview?.bringSubviewToFront(self)
}
return hitView;
}
override func pointInside(point: CGPoint, withEvent event: UIEvent?) -> Bool {
let rect = self.bounds
var isInside = CGRectContainsPoint(rect, point)
if(!isInside) {
for view in self.subviews {
isInside = CGRectContainsPoint(view.frame, point)
break;
}
}
return isInside
}
Ответ 4
Вот лучший пример представления CallOut
http://www.cocoacontrols.com/platforms/ios/controls/gikanimatedcallout
http://www.cocoacontrols.com/platforms/ios/controls/multirowcalloutannotationview
Ответ 5
Я только что создал настраиваемую выноску для моего вида карты, которая позволяет избежать проблем, когда выноска исчезает при нажатии. Здесь - это Gist с шагами, которые я сделал.