Najlepszym sposobem, w jaki udało mi się to osiągnąć, jest Rozpoznawanie gestów. Inne sposoby okazują się obejmować dużo hakerskiego programowania, które niedoskonale powiela kod Apple, szczególnie w przypadku multitouch.
Oto, co robię: Zaimplementuj aparat rozpoznawania gestów, któremu nie można zapobiec i który nie może uniemożliwić innym rozpoznawania gestów. Dodaj go do widoku mapy, a następnie użyj gestu Dotyk Rozpoznawania Rozpoczynający, dotknięcia Przeniesiony itp. Według własnego uznania.
Jak wykryć dowolne dotknięcie w MKMapView (bez sztuczek)
WildcardGestureRecognizer * tapInterceptor = [[WildcardGestureRecognizer alloc] init];
tapInterceptor.touchesBeganCallback = ^(NSSet * touches, UIEvent * event) {
self.lockedOnUserLocation = NO;
};
[mapView addGestureRecognizer:tapInterceptor];
WildcardGestureRecognizer.h
//
// WildcardGestureRecognizer.h
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import <Foundation/Foundation.h>
typedef void (^TouchesEventBlock)(NSSet * touches, UIEvent * event);
@interface WildcardGestureRecognizer : UIGestureRecognizer {
TouchesEventBlock touchesBeganCallback;
}
@property(copy) TouchesEventBlock touchesBeganCallback;
@end
WildcardGestureRecognizer.m
//
// WildcardGestureRecognizer.m
// Created by Raymond Daly on 10/31/10.
// Copyright 2010 Floatopian LLC. All rights reserved.
//
#import "WildcardGestureRecognizer.h"
@implementation WildcardGestureRecognizer
@synthesize touchesBeganCallback;
-(id) init{
if (self = [super init])
{
self.cancelsTouchesInView = NO;
}
return self;
}
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
if (touchesBeganCallback)
touchesBeganCallback(touches, event);
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event
{
}
- (void)reset
{
}
- (void)ignoreTouch:(UITouch *)touch forEvent:(UIEvent *)event
{
}
- (BOOL)canBePreventedByGestureRecognizer:(UIGestureRecognizer *)preventingGestureRecognizer
{
return NO;
}
- (BOOL)canPreventGestureRecognizer:(UIGestureRecognizer *)preventedGestureRecognizer
{
return NO;
}
@end
SWIFT 3
let tapInterceptor = WildCardGestureRecognizer(target: nil, action: nil)
tapInterceptor.touchesBeganCallback = {
_, _ in
self.lockedOnUserLocation = false
}
mapView.addGestureRecognizer(tapInterceptor)
WildCardGestureRecognizer.swift
import UIKit.UIGestureRecognizerSubclass
class WildCardGestureRecognizer: UIGestureRecognizer {
var touchesBeganCallback: ((Set<UITouch>, UIEvent) -> Void)?
override init(target: Any?, action: Selector?) {
super.init(target: target, action: action)
self.cancelsTouchesInView = false
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
super.touchesBegan(touches, with: event)
touchesBeganCallback?(touches, event)
}
override func canPrevent(_ preventedGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
override func canBePrevented(by preventingGestureRecognizer: UIGestureRecognizer) -> Bool {
return false
}
}
video
tag HTML5 z kontrolkami, moduł rozpoznawania gestów uniemożliwi użytkownikowi korzystanie z tych elementów sterujących. Szukałem obejścia tego problemu, ale jeszcze go nie znalazłem.Po całym dniu pizzy i krzyków w końcu znalazłem rozwiązanie! Bardzo schludny!
Peter, użyłem twojej sztuczki powyżej i trochę go poprawiłem, aby w końcu mieć rozwiązanie, które doskonale współpracuje z MKMapView i powinno działać również z UIWebView
MKTouchAppDelegate.h
MKTouchAppDelegate.m
UIViewTouch.h
UIViewTouch.m
Mam nadzieję, że niektórym z Was to pomoże!
Twoje zdrowie
źródło
źródło
W przypadku MKMapView prawdziwym działającym rozwiązaniem jest rozpoznawanie gestów!
Ja chciałem przestać aktualizować środek mapy w mojej lokalizacji, gdy przeciągam mapę lub szczypię, aby powiększyć.
Zatem utwórz i dodaj swój aparat rozpoznawania gestów do mapView:
Przejrzyj odwołanie do klasy UIGestureRecognizer, aby wyświetlić wszystkie dostępne narzędzia do rozpoznawania gestów.
Ponieważ zdefiniowaliśmy delegata do siebie, musimy zaimplementować protokół UIGestureRecognizerDelegate:
I zastąp metodę gestRecognizer: GestRecognizer shouldRecognizeSimultacentWithGestureRecognizer: aby umożliwić rozpoznawanie wielu gestów jednocześnie, jeśli dobrze zrozumiałem:
Teraz napisz metody, które będą wywoływane przez nasze rozpoznawanie gestów:
źródło
Na wypadek, gdyby ktoś próbował zrobić to samo co ja: chciałem utworzyć adnotację w miejscu, w którym użytkownik stuka. Do tego użyłem
UITapGestureRecognizer
rozwiązania:Jednak
didTapOnMap:
został również wywołany, gdy dotknąłem adnotacji i utworzono nową. Rozwiązaniem jest wdrożenieUIGestureRecognizerDelegate
:źródło
MKAnnotation
. W takim przypadku możesz mieć widok podrzędny innej adnotacji wyzwalający rozpoznawanie gestów. Musiałem rekurencyjnie sprawdzić podgląd touch.view, aby znaleźć potencjalny MKAnnotationViewPrawdopodobnie będziesz musiał nałożyć przezroczysty widok, aby uchwycić dotknięcia, tak jak to się często dzieje w przypadku kontrolek opartych na UIWebView. Widok mapy robi już wiele specjalnych rzeczy za pomocą dotyku, aby umożliwić przesuwanie, wyśrodkowanie, powiększanie mapy itp., Że wiadomości nie są wyświetlane w aplikacji.
Dwie inne (NIETESTOWANE) opcje, które przychodzą mi do głowy:
1) Zrezygnuj z pierwszej osoby odpowiadającej za pośrednictwem IB i ustaw ją na „Właściciel pliku”, aby umożliwić właścicielowi pliku reagowanie na dotknięcia. Wątpię, czy to zadziała, ponieważ MKMapView rozszerza NSObject, a nie UIView, w wyniku czego zdarzenia dotykowe nadal mogą nie być propagowane do Ciebie.
2) Jeśli chcesz przechwytywać zmiany stanu mapy (na przykład przy powiększaniu), po prostu zaimplementuj protokół MKMapViewDelegate, aby nasłuchiwać określonych zdarzeń. Moje przeczucie jest takie, że jest to najlepsza szansa na łatwe przechwycenie niektórych interakcji (poza implementacją przezroczystego widoku na mapie). Nie zapomnij ustawić kontrolera widoku mieszczącego MKMapView jako delegata mapy (
map.delegate = self
).Powodzenia.
źródło
Nie eksperymentowałem, ale istnieje duża szansa, że MapKit jest oparty na klastrze klas, dlatego tworzenie podklas jest trudne i nieskuteczne.
Sugerowałbym, aby widok MapKit był widokiem podrzędnym widoku niestandardowego, który powinien umożliwiać przechwytywanie zdarzeń dotykowych, zanim do niego dotrą.
źródło
Tak więc po pół dnia zabawy z tym znalazłem:
W filmach na temat iPhone'a ze Stanforda pewien facet z Apple mówi, że wiele rzeczy związanych z UIKit spowoduje wiele błędów, jeśli „prześlesz” żądania dotyku (czyli dwie metody opisane powyżej) i prawdopodobnie nie zadziała.
ROZWIĄZANIE : jest opisane tutaj: Przechwytywanie / przechwytywanie zdarzeń dotykowych iPhone'a dla MKMapView . Zasadniczo „łapiesz” zdarzenie, zanim otrzyma je jakikolwiek respondent i tam je interpretujesz.
źródło
W Swift 3.0
źródło
Ustaw widok MKMapView jako widok podrzędny widoku niestandardowego i zaimplementuj
w widoku niestandardowym, aby zwrócić siebie zamiast widoku podrzędnego.
źródło
Dzięki za pizzę i krzyki - zaoszczędziłeś mi dużo czasu.
multipletouchenabled będzie działać sporadycznie.
W końcu zmieniłem widoki, kiedy musiałem uchwycić dotyk (inny punkt w czasie niż potrzeba pinchzoomów):
źródło
Zauważyłem, że możesz śledzić liczbę i lokalizację dotknięć, a także uzyskać lokalizację każdego z nich w widoku:
Czy ktoś inny próbował użyć tych wartości, aby zaktualizować poziom powiększenia mapy? To byłaby kwestia zapisania pozycji startowych, a następnie końcowych, obliczenia względnej różnicy i aktualizacji mapy.
Bawię się podstawowym kodem dostarczonym przez Martina i wygląda na to, że zadziała ...
źródło
Oto, co stworzyłem, co pozwala na przybliżanie przez szczypanie w symulatorze (nie próbowałem na prawdziwym iPhonie), ale myślę, że byłoby dobrze:
Główną ideą jest to, że jeśli użytkownik używa dwóch palców, można śledzić wartości. Zapisuję punkty początkowe i końcowe w punktach początkowych A i B. Następnie zapisuję bieżące punkty śledzenia, a kiedy skończę, po dotknięciu Koniec, mogę wywołać procedurę, aby obliczyć względne długości linii między punktami, od których zaczynam i linię między punktem, który kończę za pomocą prostego obliczenia przeciwprostokątnego. Stosunek między nimi to wielkość powiększenia: mnożę zakres regionu przez tę wartość.
Mam nadzieję, że to komuś się przyda.
źródło
Pomysł „nakładkowego” przezroczystego widoku zaczerpnąłem z odpowiedzi MystikSpiral i działał on doskonale w tym, co próbowałem osiągnąć; szybkie i czyste rozwiązanie.
Krótko mówiąc, miałem niestandardowy UITableViewCell (zaprojektowany w IB) z MKMapView po lewej stronie i kilkoma etykietami UIL po prawej. Chciałem zrobić niestandardową komórkę, aby można było jej dotknąć w dowolnym miejscu, a to spowodowałoby uruchomienie nowego kontrolera widoku. Jednak dotknięcie mapy nie spowodowało dotknięcia `` w górę '' do UITableViewCell, dopóki po prostu nie dodałem UIView o tym samym rozmiarze co widok mapy bezpośrednio nad nią (w IB) i nie nadałem jego tła `` wyraźnego koloru '' w kodzie ( nie sądzisz, że możesz ustawić clearColor w IB ??):
Pomyślałem, że może to pomóc komuś innemu; z pewnością, jeśli chcesz osiągnąć to samo zachowanie dla komórki widoku tabeli.
źródło