Как добавить пользовательский вид в аннотации на карте

Вот мой код Я хочу добавить свой собственный вид выноски вместо 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;
        }

}

Изображение для справки

6 ответов

У меня была та же проблема, и в итоге я сделал следующее:

Когда я получаю обратный вызов делегата mapView

-(void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view

(пришло время, когда я хочу показать свой пользовательский CalloutView)

Я использую представление, полученное как представление параметра * (MKAnnotationView ) (которое является представлением вывода), и просто добавляю свое настраиваемое представление в это представление вывода, используя

 [view addSubview:customView];

Он добавит ваш пользовательский вид поверх этого вида выводов, поэтому, если мы хотим, чтобы он был выше выводов, нам нужно изменить свойство центра представлений вида следующим образом:

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];

В моем случае это выглядит так

! ПРИМЕЧАНИЕ:

Есть одно предупреждение, которое, однако, может быть легко исправлено, ваш пользовательский вид будет игнорировать события касания, потому что 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;
}

Все сделано!

Я создал библиотеку для показа пользовательских выносок.

https://github.com/s3lvin/DXCustomCallout-ObjC

Вы можете передать любой пользовательский вид для выноски! Он также поддерживает события для UIControls.

Пользовательский вынос

На лучший ответ выше в 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
}

Я только что создал настраиваемую выноску для вида карты, которая позволяет избежать проблем с исчезновением выноски при нажатии. Вот Гист с шагами, которые я сделал.

Вы можете использовать эту библиотеку. Он также предоставляет готовый шаблон для представления выноски. Добавляет интересные анимации и привязку для ваших пользовательских видов.

https://github.com/okhanokbay/MapViewPlus

введите описание изображения здесь введите описание изображения здесь

Другие вопросы по тегам