Le meilleur moyen que j'ai trouvé pour y parvenir est d'utiliser un outil de reconnaissance de gestes. D'autres moyens s'avèrent impliquer beaucoup de programmation hackish qui duplique imparfaitement le code d'Apple, en particulier dans le cas du multitouch.
Voici ce que je fais: implémenter un outil de reconnaissance de mouvement qui ne peut pas être empêché et qui ne peut pas empêcher d'autres outils de reconnaissance de mouvement. Ajoutez-le à la vue de la carte, puis utilisez les touches gestureRecognizer, touchBegan, touchMoved, etc. à votre guise.
Comment détecter n'importe quel robinet dans un MKMapView (sans astuces)
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
balise HTML5 avec des contrôles, le module de reconnaissance de mouvement empêchera l'utilisateur de pouvoir utiliser les contrôles. Je cherchais une solution de contournement pour cela, mais je n'en ai pas encore trouvé.Après une journée de pizzas, de cris, j'ai enfin trouvé la solution! Très propre!
Peter, j'ai utilisé votre astuce ci-dessus et l'ai un peu peaufiné pour enfin avoir une solution qui fonctionne parfaitement avec MKMapView et devrait également fonctionner avec UIWebView
MKTouchAppDelegate.h
MKTouchAppDelegate.m
UIViewTouch.h
UIViewTouch.m
J'espère que cela aidera certains d'entre vous!
À votre santé
la source
la source
Pour un MKMapView, la vraie solution de travail est la reconnaissance des gestes!
Moi je voulais arrêter de mettre à jour le centre de la carte sur ma position lorsque je fais glisser la carte ou la pince pour zoomer.
Alors, créez et ajoutez votre outil de reconnaissance de gestes à la mapView:
Consultez la référence de classe UIGestureRecognizer pour voir tous les outils de reconnaissance de mouvement disponibles.
Parce que nous avons défini le délégué à self, nous devons implémenter le protocole UIGestureRecognizerDelegate:
Et écraser la méthode gestureRecognizer: gestureRecognizer shouldRecognizeSimultaneousWithGestureRecognizer: afin de permettre de reconnaître plusieurs gestes simultanément, si j'ai bien compris:
Maintenant, écrivez les méthodes qui seront appelées par nos outils de reconnaissance de gestes:
la source
Juste au cas où quelqu'un essaie de faire la même chose comme moi: je voulais créer une annotation au point où l'utilisateur tape. Pour cela, j'ai utilisé la
UITapGestureRecognizer
solution:Cependant,
didTapOnMap:
a également été appelé lorsque j'ai tapé sur l'annotation et une nouvelle serait créée. La solution consiste à implémenterUIGestureRecognizerDelegate
:la source
MKAnnotation
. Dans ce cas, vous pouvez avoir une sous-vue d'une autre annotation déclenchant la reconnaissance de mouvement. J'ai dû vérifier récursivement la supervision du touch.view pour trouver un potentiel MKAnnotationViewVous devrez probablement superposer une vue transparente pour capturer les touches, comme cela se fait souvent avec les contrôles basés sur UIWebView. La vue de la carte fait déjà un tas de choses spéciales avec une touche afin de permettre à la carte d'être déplacée, centrée, zoomée, etc ... afin que les messages ne soient pas diffusés dans votre application.
Deux autres options (UNTESTED) auxquelles je peux penser:
1) Démissionnez le premier répondeur via IB et réglez-le sur "File's Owner" pour permettre au propriétaire du fichier de répondre aux touches. Je doute que cela fonctionne parce que MKMapView étend NSObject, pas UIView et par conséquent, les événements tactiles peuvent ne pas être propagés jusqu'à vous.
2) Si vous souhaitez intercepter lorsque l'état de la carte change (comme sur un zoom), implémentez simplement le protocole MKMapViewDelegate pour écouter des événements particuliers. Mon intuition est que c'est votre meilleur moyen de piéger facilement certaines interactions (à moins d'implémenter la vue transparente sur la carte). N'oubliez pas de définir le contrôleur de vue hébergeant MKMapView comme délégué de la carte (
map.delegate = self
).Bonne chance.
la source
Je n'ai pas expérimenté, mais il y a de fortes chances que MapKit soit basé sur un cluster de classes, et par conséquent, le sous-classer est difficile et inefficace.
Je suggère de faire de la vue MapKit une sous-vue d'une vue personnalisée, ce qui devrait vous permettre d'intercepter les événements tactiles avant qu'ils ne l'atteignent.
la source
Donc, après une demi-journée de déconner avec cela, j'ai trouvé ce qui suit:
Dans les vidéos iPhone de Stanford, un gars d'Apple dit que beaucoup de choses UIKit causeront beaucoup d'erreurs si vous "transférez" les requêtes tactiles (alias les deux méthodes décrites ci-dessus), et que vous ne les obtiendrez probablement pas.
LA SOLUTION : est décrite ici: Interception / Détournement d'événements iPhone Touch pour MKMapView . Fondamentalement, vous «attrapez» l'événement avant qu'un répondeur ne l'obtienne, et l'interprétez là.
la source
Dans Swift 3.0
la source
Faire de MKMapView une sous-vue d'une vue personnalisée et implémenter
dans la vue personnalisée pour renvoyer soi au lieu de la sous-vue.
la source
Merci pour la pizza et les cris - vous m'avez fait gagner beaucoup de temps.
multipletouchenabled fonctionnera sporadiquement.
En fin de compte, j'ai changé les vues lorsque je devais capturer le toucher (moment différent de celui des zooms pincés):
la source
Je remarque que vous pouvez suivre le nombre et l'emplacement des touches, et obtenir l'emplacement de chacune dans une vue:
Quelqu'un d'autre a-t-il essayé d'utiliser ces valeurs pour mettre à jour le niveau de zoom de la carte? Il s'agirait d'enregistrer les positions de départ, puis les emplacements d'arrivée, de calculer la différence relative et de mettre à jour la carte.
Je joue avec le code de base fourni par Martin, et il semble que cela fonctionnera ...
la source
Voici ce que j'ai mis en place, qui permet des zooms pincés dans le simulateur (je n'ai pas essayé sur un vrai iPhone), mais je pense que ça irait:
L'idée principale est que si l'utilisateur utilise deux doigts, vous suivez les valeurs. J'enregistre les points de départ et de fin dans les points de départ A et B.Ensuite, j'enregistre les points de suivi actuels, et lorsque j'ai terminé, sur touchEnded, je peux appeler une routine pour calculer les longueurs relatives de la ligne entre les points avec lesquels je commence , et la ligne entre le point où je termine en utilisant une simple hypoténuse calc. Le rapport entre eux est la quantité de zoom: je multiplie la portée de la région par cette quantité.
J'espère que c'est utile à quelqu'un.
la source
J'ai pris l'idée d'une vue transparente "superposée", de la réponse de MystikSpiral, et cela a parfaitement fonctionné pour ce que j'essayais de réaliser; solution rapide et propre.
En bref, j'avais un UITableViewCell personnalisé (conçu en IB) avec un MKMapView sur le côté gauche et quelques UILabels sur la droite. Je voulais créer la cellule personnalisée afin que vous puissiez la toucher n'importe où et cela pousserait un nouveau contrôleur de vue. Cependant, toucher la carte ne passait pas de touches `` vers le haut '' à UITableViewCell jusqu'à ce que j'aie simplement ajouté un UIView de la même taille que la vue de la carte juste au-dessus (dans IB) et que son arrière-plan soit la `` couleur claire '' dans le code ( ne pensez pas que vous pouvez définir clearColor dans IB ??):
Je pensais que cela pourrait aider quelqu'un d'autre; certainement si vous souhaitez obtenir le même comportement pour une cellule de vue tableau.
la source