Der beste Weg, dies zu erreichen, ist mit einem Gestenerkenner. Andere Möglichkeiten beinhalten eine Menge hackiger Programmierung, die Apples Code unvollständig dupliziert, insbesondere im Fall von Multitouch.
Folgendes mache ich: Implementiere einen Gestenerkenner, der nicht verhindert werden kann und der andere Gestenerkenner nicht verhindern kann. Fügen Sie es der Kartenansicht hinzu und verwenden Sie dann die BerührungenBegan, touchMoved usw. des gestureRecognizer nach Ihren Wünschen.
So erkennen Sie einen Tipp in einem MKMapView (ohne Tricks)
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 mit Steuerelementen enthält, verhindert die Gestenerkennung, dass der Benutzer die Steuerelemente verwenden kann. Ich habe nach einer Problemumgehung gesucht, aber noch keine gefunden.Nach einem Tag voller Pizzen und Schreie fand ich endlich die Lösung! Sehr gepflegt!
Peter, ich habe deinen obigen Trick benutzt und ihn ein wenig optimiert, um endlich eine Lösung zu haben, die perfekt mit MKMapView funktioniert und auch mit UIWebView funktionieren sollte
MKTouchAppDelegate.h
MKTouchAppDelegate.m
UIViewTouch.h
UIViewTouch.m
Ich hoffe das wird einigen von euch helfen!
Prost
quelle
quelle
Für ein MKMapView ist die eigentliche Arbeitslösung die Gestenerkennung!
Ich wollte die Aktualisierung der Kartenmitte an meinem Standort beenden, wenn ich die Karte ziehe oder zum Zoomen kneife.
Erstellen Sie also Ihren Gestenerkenner und fügen Sie ihn der mapView hinzu:
In der UIGestureRecognizer-Klassenreferenz finden Sie alle verfügbaren Gestenerkenner.
Da wir den Delegaten für sich selbst definiert haben, müssen wir das Protokoll UIGestureRecognizerDelegate implementieren:
Und überschreiben Sie die Methode gestureRecognizer: gestureRecognizer shouldRecognizeSimultaneousWithGestureRecognizer: um das gleichzeitige Erkennen mehrerer Gesten zu ermöglichen, wenn ich richtig verstanden habe:
Schreiben Sie nun die Methoden, die von unseren Gestenerkennern aufgerufen werden:
quelle
Nur für den Fall, dass jemand versucht, dasselbe wie ich zu tun: Ich wollte an der Stelle, an der der Benutzer tippt, eine Anmerkung erstellen. Dafür habe ich die
UITapGestureRecognizer
Lösung verwendet:Wurde
didTapOnMap:
jedoch auch aufgerufen, als ich auf die Anmerkung tippte und eine neue erstellt wurde. Die Lösung besteht darin, Folgendes zu implementierenUIGestureRecognizerDelegate
:quelle
MKAnnotation
. In diesem Fall kann die Unteransicht einer anderen Anmerkung die Gestenerkennung auslösen. Ich musste rekursiv die Übersicht der touch.view überprüfen, um eine mögliche MKAnnotationViewWahrscheinlich müssen Sie eine transparente Ansicht überlagern, um die Berührungen zu erfassen, wie dies bei UIWebView-basierten Steuerelementen so häufig der Fall ist. In der Kartenansicht werden bereits einige spezielle Aufgaben mit einem Tastendruck ausgeführt, damit die Karte verschoben, zentriert, gezoomt usw. werden kann, damit die Nachrichten nicht in Ihre App gelangen.
Zwei weitere (UNTESTED) Optionen, die mir einfallen:
1) Geben Sie den Ersthelfer über IB zurück und setzen Sie ihn auf "Dateibesitzer", damit der Dateibesitzer auf die Berührungen reagieren kann. Ich bin mir nicht sicher, ob dies funktionieren wird, da MKMapView NSObject erweitert, nicht UIView und ein Ergebnis, bei dem die Berührungsereignisse möglicherweise immer noch nicht an Sie weitergegeben werden.
2) Wenn Sie einfangen möchten, wenn sich der Map-Status ändert (z. B. bei einem Zoom), implementieren Sie einfach das MKMapViewDelegate-Protokoll, um auf bestimmte Ereignisse zu warten. Meine Vermutung ist, dass dies Ihre beste Möglichkeit ist, Interaktionen leicht einzufangen (ohne die transparente Ansicht über die Karte zu implementieren). Vergessen Sie nicht, den View Controller, in dem sich das MKMapView befindet, als Delegat der Karte festzulegen (
map.delegate = self
).Viel Glück.
quelle
Ich habe nicht experimentiert, aber es besteht eine gute Chance, dass MapKit auf einem Klassencluster basiert, und daher ist es schwierig und ineffektiv, es in Unterklassen zu unterteilen.
Ich würde vorschlagen, die MapKit-Ansicht zu einer Unteransicht einer benutzerdefinierten Ansicht zu machen, damit Sie Berührungsereignisse abfangen können, bevor sie diese erreichen.
quelle
Nachdem ich einen halben Tag damit herumgespielt hatte, fand ich Folgendes:
In den Stanford iPhone-Videos sagt ein Mann von Apple, dass viele der UIKit-Dinge eine Menge Fehler verursachen, wenn Sie die Berührungsanforderungen "übertragen" (auch bekannt als die beiden oben beschriebenen Methoden), und Sie werden sie wahrscheinlich nicht zum Laufen bringen.
DIE LÖSUNG : wird hier beschrieben: Abfangen / Entführen von iPhone Touch-Ereignissen für MKMapView . Grundsätzlich "fangen" Sie das Ereignis, bevor ein Antwortender es erhält, und interpretieren es dort.
quelle
In Swift 3.0
quelle
Machen Sie die MKMapView zu einer Unteransicht einer benutzerdefinierten Ansicht und implementieren Sie sie
in der benutzerdefinierten Ansicht, um self anstelle der Unteransicht zurückzugeben.
quelle
Danke für die Pizza und die Schreie - du hast mir viel Zeit gespart.
multipletouchenabled funktioniert sporadisch.
Am Ende habe ich die Ansichten ausgeschaltet, als ich die Berührung erfassen musste (anderer Zeitpunkt als Pinchzooms):
quelle
Ich stelle fest, dass Sie die Anzahl und den Ort der Berührungen verfolgen und die Position der einzelnen Berührungen in einer Ansicht abrufen können:
Hat jemand anderes versucht, diese Werte zu verwenden, um die Zoomstufe der Karte zu aktualisieren? Es geht darum, die Startpositionen und dann die Zielpositionen aufzuzeichnen, die relative Differenz zu berechnen und die Karte zu aktualisieren.
Ich spiele mit dem von Martin bereitgestellten Basiscode und das sieht so aus, als würde es funktionieren ...
quelle
Folgendes habe ich zusammengestellt, um das Zoomen im Simulator zu ermöglichen (ich habe es noch nicht auf einem echten iPhone versucht), aber ich denke, das wäre in Ordnung:
Die Hauptidee ist, dass Sie die Werte verfolgen, wenn der Benutzer zwei Finger verwendet. Ich zeichne die Start- und Endpunkte in den Startpunkten A und B auf. Dann zeichne ich die aktuellen Verfolgungspunkte auf. Wenn ich fertig bin, kann ich bei touchEnded eine Routine aufrufen, um die relativen Längen der Linie zwischen den Punkten zu berechnen, mit denen ich beginne und die Linie zwischen dem Punkt, an dem ich mit der einfachen Berechnung der Hypotenuse ende. Das Verhältnis zwischen ihnen ist der Zoombetrag: Ich multipliziere die Bereichsspanne mit diesem Betrag.
Hoffe, es ist nützlich für jemanden.
quelle
Ich habe die Idee einer transparenten "Overlay" -Ansicht aus MystikSpirals Antwort übernommen und sie funktionierte perfekt für das, was ich erreichen wollte. schnelle und saubere Lösung.
Kurz gesagt, ich hatte eine benutzerdefinierte UITableViewCell (in IB entworfen) mit einem MKMapView auf der linken Seite und einigen UILabels auf der rechten Seite. Ich wollte die benutzerdefinierte Zelle so gestalten, dass Sie sie überall berühren können, und dies würde einen neuen Ansichts-Controller auslösen. Durch Berühren der Karte wurden jedoch keine Berührungen an die UITableViewCell übergeben, bis ich einfach eine UIView mit der gleichen Größe wie die Kartenansicht direkt darüber (in IB) hinzugefügt und den Hintergrund im Code als "klare Farbe" festgelegt habe (in IB). glaube nicht, dass du clearColor in IB setzen kannst ??):
Dachte, es könnte jemand anderem helfen; sicherlich, wenn Sie dasselbe Verhalten für eine Tabellenansichtszelle erzielen möchten.
quelle