Как сделать MKAnnotationView сенсорным? - PullRequest
9 голосов
/ 27 декабря 2011

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

Ответы [ 4 ]

18 голосов
/ 28 декабря 2011

Для этого вам нужно создать подкласс 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 состоит в том, чтобы предотвратить выбор моей пользовательской аннотации, я использую ее как настраиваемую / интерактивную выноску из контактов карты, и это сохраняет контакт, к которому он относится, к выбранному, вместо того, чтобы позволить изменению выбора на эту аннотацию .

1 голос
/ 28 декабря 2011

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

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

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

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

0 голосов
/ 19 сентября 2017
Решение

@ jhabbott никогда не работало для меня, как я уже говорил здесь .

У меня есть изображение и ярлык рядом. Изображение было показано с помощью свойства 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:) переопределения, которые ничего не сделали.

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

0 голосов
/ 27 декабря 2011

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

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

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

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...