Определить, находится ли касание внутри или снаружи настраиваемого выноски. - PullRequest
0 голосов
/ 03 апреля 2020

У меня есть карта с некоторыми булавками. Когда я нажимаю на PIN-код, пользовательский выноска отображается как UIView. Когда я нажимаю внутри calloutView, ничего не должно происходить. Если я нажимаю вне представления, пользовательский calloutView должен исчезнуть. Но я не знаю, как это реализовать, либо он исчезает при касаниях внутри и снаружи представления, либо вообще не исчезает.

мое удовольствие c обрабатывать касания:

    func mapView(_ mapView: MKMapView, didDeselect view: MKAnnotationView) {
    if view == customCallout {
        return
    } else {
        customCallout?.removeFromSuperview()
    }
}

В этом случае он удаляет на обоих касаниях пользовательский вынос. Здесь я создаю выноску:

func mapView(_ mapView: MKMapView, didSelect view: MKAnnotationView) {
    if view.annotation is MKUserLocation {
        return
    }
    //this creates the callout
    let views = Bundle.main.loadNibNamed("CustomCalloutView", owner: nil, options: nil)
    let calloutView =  views?[0] as! CustomCalloutView
    calloutView.delegate = self
    customCallout = calloutView
}

, как я могу реализовать это, если я коснусь внутри настраиваемого вида выноски, он не исчезнет, ​​но в случае что я нажимаю снаружи, оно исчезает?

1 Ответ

0 голосов
/ 07 апреля 2020

Старое Руководство по программированию местоположения и карт описывает процесс. Техника включает в себя реализацию метода hitTest для представления аннотации, который включает попадания в ваш пользовательский выноски. В противном случае касания не распознаются как часть представления аннотации и / или выноски, а скорее на карте.

Как гласит Guide :

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

  1. Разработка подкласса NSView или UIView, представляющего настраиваемую выноску. Вероятно, подкласс должен реализовать метод drawRect: для рисования вашего пользовательского содержимого.
  2. Создать контроллер представления, который инициализирует представление выноски и выполняет действие, связанное с кнопкой.
  3. В представление аннотации, реализуйте hitTest: для ответа на попадания, которые находятся за пределами представления аннотации, но находятся за пределами представления выноски, как показано в Перечислении 6-7.
  4. В представлении аннотации реализуйте setSelected: animated: to add ваше представление выноски как подпредставление представления аннотации, когда пользователь щелкает или нажимает на него. Если представление выноски уже видно, когда пользователь выбирает его, метод setSelected: должен удалить подпредставление выноски из представления аннотации (см. Листинг 6-8).
  5. В методе представления аннотации initWithAnnotation: метод установите Свойство canShowCallout имеет значение NO, чтобы предотвратить отображение на карте стандартной выноски, когда пользователь выбирает аннотацию.
  6. В листинге 6-7 показан пример реализации hitTest: для обработки попаданий в представлении выноски, которые могут находиться за пределами границ. представления аннотаций.

Перечисление 6-7 Отвечая на попадания в пользовательском выноске

- (NSView *)hitTest:(NSPoint)point
{
    NSView *hitView = [super hitTest:point];
    if (hitView == nil && self.selected) {
        NSView *calloutView = self.calloutViewController.view;
        NSPoint pointInCalloutView = [self convertPoint:point toView:calloutView];
        hitView = [calloutView hitTest:pointInCalloutView];
    }
    return hitView;
}

Перечисление 6-8 показывает пример реализации setSelected: animated: для анимации появление и отклонение пользовательского представления выноски, когда пользователь выбирает представление аннотации.

Перечисление 6-8 Добавление и удаление настраиваемого представления выноски

- (void)setSelected:(BOOL)selected
{
    [super setSelected:selected];

    // Get the custom callout view.
    NSView *calloutView = self.calloutViewController.view;
    if (selected) {
        NSRect annotationViewBounds = self.bounds;
        NSRect calloutViewFrame = calloutView.frame;
      // Center the callout view above and to the right of the annotation view.
        calloutViewFrame.origin.x = -(NSWidth(calloutViewFrame) - NSWidth(annotationViewBounds)) * 0.5;
        calloutViewFrame.origin.y = -NSHeight(calloutViewFrame) + 15.0;
        calloutView.frame = calloutViewFrame;

        [self addSubview:calloutView];
    } else {
        [calloutView.animator removeFromSuperview];
    }
}

Теперь вышеприведенное очевидно Objective- C (и ваша реализация списка 6-8, вероятно, будет отличаться от eirs), но базовый шаблон c такой же в Swift. См. CustomMapViewAnnotationCalloutSwift Репозиторий Github, который иллюстрирует, как реализовать настраиваемые представления аннотаций (включая это желаемое поведение hitTest) в Swift. Таким образом, это комбинация реализации hitTest в представлении аннотации, а также очевидно, что обратный вызов потребляет и эти штрихи.

...