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