2011-12-27 2 views
8

В настоящее время у меня есть вид на карту с некоторой аннотацией на нем. У меня есть аннотация с пользовательскими изображениями. Проблема, которую я пытаюсь исправить, - это чувствительность изображений. Когда я пытаюсь перетащить их, мне кажется, что я должен коснуться точного центра, чтобы его можно было сфокусировать. Есть ли способ увеличить границы касания?Как сделать MKAnnotationView сенсорным?

ответ

17

Для этого вам необходимо подкласс MKAnnotationView, чтобы создать свой собственный MKAnnotationView. В вашем подклассе отменяет следующие функции:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    // Return YES if the point is inside an area you want to be touchable 
} 

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    // Return the deepest view that the point is inside of. 
} 

Это позволяет нажимать интерактивные виды (например, кнопки и т. Д.). Реализация по умолчанию в MKAnnotationView не является строгой на pointInside и hitTest, потому что она позволяет прессам, которые на самом деле находятся внутри одной аннотации, чтобы отправить их в другую аннотацию. Он делает это, вычисляя ближайший центр аннотаций к сенсорной точке и отправляя события в эту аннотацию, так что близкие (перекрывающиеся) аннотации не блокируют друг друга от выбора. Однако в вашем случае вы, вероятно, захотите заблокировать другие аннотации, если пользователь должен выбрать и перетащить самую верхнюю аннотацию, поэтому вышеупомянутый метод, вероятно, вы хотите, иначе он установит вас на правильный путь.

EDIT: меня попросили в комментариях для примера реализации hitTest:withEvent: - Это зависит от того, что вы пытаетесь достичь. Первоначальный вопрос предложил коснуться и перетащить изображения в аннотации, тогда как в моем случае у меня есть некоторые кнопки внутри аннотации, которые я хочу быть интерактивными.Вот мой код:

- (UIView*)hitTest:(CGPoint)point withEvent:(UIEvent*)event 
{ 
    UIView* hitView = [super hitTest:point withEvent:event]; 
    if (hitView != nil) 
    { 
     // ensure that the callout appears above all other views 
     [self.superview bringSubviewToFront:self]; 

     // we tapped inside the callout 
     if (CGRectContainsPoint(self.resultView.callButton.frame, point)) 
     { 
      hitView = self.resultView.callButton; 
     } 
     else if (CGRectContainsPoint(self.resultView.addButton.frame, point)) 
     { 
      hitView = self.resultView.addButton; 
     } 
     else 
     { 
      hitView = self.resultView.viewDetailsButton; 
     } 
     [self preventSelectionChange]; 
    } 
    return hitView; 
} 

Как вы можете видеть, что это довольно просто - MKAnnotationView реализация (называется super на первой линии моей реализации) возвращает только первый (самый наружный) вид, не детализировать через просмотреть иерархию, чтобы увидеть, какой суб-просмотр на самом деле находится внутри. В моем случае я просто проверяю, находится ли сенсорное нажатие одной из трех кнопок и возвращает их. В других случаях у вас может быть простое сверление на основе прямоугольников через иерархию или более сложные тесты на удар, например, чтобы избежать прозрачных областей в вашем представлении, чтобы позволить касаниям проходить через эти части. Если вам нужно развернуть, CGRectContainsPoint можно использовать так же, как я его использовал, но не забудьте компенсировать свои точки в локальных координатах вида для каждого уровня обзора, в который вы развернулись.

Метод preventSelectionChange состоит в том, чтобы исключить возможность выбора моей пользовательской аннотации, я использую ее как настраиваемую/интерактивную выноску из выводов карты, и это связывает ее с выбранным, а не позволяет выбору изменить эту аннотацию.

+0

Не могли бы вы применить метод hitTest? – Daniel

+0

Если бы я смог повторить ваш ответ снова, я бы! Спасибо за обновление. – Daniel

+0

Привет снова, как насчет pointInside: withEvent:? Это где вы предлагаете CGRectContainsPoint? – Daniel

0

я осуществил нечто подобное следующим образом

  1. Создайте подкласс класса Жест распознаватель, который обрабатывает прикасается
  2. создать подкласс класса UIImage, этот класс использует класс распознавателя для обработки ваших жестов
  3. Используйте это в аннотации

жест распознаватель подкласс будет обрабатывать ваши жесты, если выполнить их в любой момент ИМА GE. Это должно помочь вам.

Держите нас в курсе, работал ли это решение для и ...

1

ли вы подкласс MKAnnotationView или вы изменили только установить свойство изображения это?

Вот документация по настройке свойства изображения.

Обсуждение: Назначение нового облика этого свойства также изменяет размер рамы зрения таким образом, чтобы он соответствовал ширине и высоте нового изображения. Позиция кадра представления не изменяется.

Проверьте размер рамки вашего аннотационного вида, в котором ваш объект может получить штрихи.

0

Решение @jhabbott никогда не работало для меня, как я упомянул here.

У меня есть изображение и ярлык бок о бок. Изображение было показано, путем установки annotationview image свойство, а метка путем добавления UILabel

Я перенаправил func point(inside:with:) метод к UILabel один (который включал в зону изображения) и hitTest действительно возвращался точно такой же вид нажал ли я на ярлык или изображение. Но ярлык нажмите не добавлялись обратного вызова ...

Наконец, я в конечном итоге за счет увеличения кадра MKAnnotationView вложить этикетку + изображение, я поставил annotationView.image в nil, и я создал свой обычай UIImageView.

Потому что я хотел узловую точку в середине изображения, я должен был установить обычай один:

self.frame = CGRect(x: 0, y: 0, width: 
self.myLabel.frame.width, height: self.myLabel.frame.height) 
self.centerOffset = CGPoint(x: self.frame.width/2, y: self.myImageView.frame.height/2) 

Тогда я удален point(inside:with:) и hitTest(point:with:) переопределение, что ничего не сделали.

И теперь, в первый раз, мой аннотационный вид полностью реактивный.

Смежные вопросы