A melhor maneira que encontrei de fazer isso é com um Reconhecedor de gestos. Outras maneiras envolvem muita programação hackeada que duplica imperfeitamente o código da Apple, especialmente no caso do multitoque.
Aqui está o que eu faço: implementar um reconhecedor de gestos que não pode ser evitado e que não pode impedir outros reconhecedores de gestos. Adicione-o à visualização do mapa e, em seguida, use os toquesBegan, toquesMovidos, etc. de gestoRecognizer, conforme desejar.
Como detectar qualquer toque dentro de um MKMapView (sem truques)
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 com controles, o reconhecedor de gestos impedirá que o usuário seja capaz de usar os controles. Tenho procurado uma solução alternativa para isso, mas ainda não encontrei uma.Depois de um dia de pizzas, gritos, finalmente encontrei a solução! Muito legal!
Peter, eu usei seu truque acima e o ajustei um pouco para finalmente ter uma solução que funcione perfeitamente com MKMapView e deve funcionar também com UIWebView
MKTouchAppDelegate.h
MKTouchAppDelegate.m
UIViewTouch.h
UIViewTouch.m
Espero que ajude alguns de vocês!
Felicidades
fonte
fonte
Para um MKMapView, a verdadeira solução de trabalho é o reconhecimento de gestos!
Eu Queria parar de atualizar o centro do mapa na minha localização quando arrasto o mapa ou aperto para aumentar o zoom.
Portanto, crie e adicione seu reconhecedor de gestos ao mapView:
Consulte a Referência de classe UIGestureRecognizer para ver todos os reconhecedores de gestos disponíveis.
Como definimos o delegado para self, temos que implementar o protocolo UIGestureRecognizerDelegate:
E substituir o método gestoRecognizer: gestRecognizer shouldRecognizeSimultaneousWithGestureRecognizer: para permitir reconhecer vários gestos simultaneamente, se entendi direito:
Agora escreva os métodos que serão chamados por nossos reconhecedores de gestos:
fonte
Caso alguém esteja tentando fazer o mesmo como eu: eu queria criar uma anotação no ponto onde o usuário toca. Para isso usei a
UITapGestureRecognizer
solução:No entanto,
didTapOnMap:
também foi chamado quando toquei na anotação e uma nova seria criada. A solução é implementarUIGestureRecognizerDelegate
:fonte
MKAnnotation
. Nesse caso, você pode ter outra subvisualização de anotação acionando o reconhecedor de gestos. Tive que verificar recursivamente o superview do touch.view para encontrar um potencial MKAnnotationViewProvavelmente, você precisará sobrepor uma visualização transparente para captar os toques, da mesma forma que costuma ser feito com os controles baseados em UIWebView. O Map View já faz um monte de coisas especiais com um toque para permitir que o mapa seja movido, centralizado, ampliado, etc ... para que as mensagens não borbulhem no seu aplicativo.
Posso pensar em duas outras opções (NÃO TESTADAS):
1) Renuncie o primeiro a responder via IB e defina-o como "Proprietário do arquivo" para permitir que o proprietário do arquivo responda aos toques. Tenho dúvidas de que isso funcionará porque MKMapView estende NSObject, não UIView e, como resultado, os eventos de toque ainda podem não ser propagados para você.
2) Se você deseja capturar quando o estado do mapa muda (como em um zoom), apenas implemente o protocolo MKMapViewDelegate para ouvir eventos específicos. Meu palpite é que essa é sua melhor chance de capturar alguma interação facilmente (exceto implementar a visão transparente sobre o mapa). Não se esqueça de definir o View Controller que hospeda o MKMapView como o delegado do mapa (
map.delegate = self
).Boa sorte.
fonte
Eu não experimentei, mas há uma boa chance do MapKit ser baseado em um cluster de classes e, portanto, subclassificá-lo é difícil e ineficaz.
Eu sugiro fazer o MapKit view uma subvisão de uma visão customizada, que deve permitir que você intercepte eventos de toque antes que eles cheguem.
fonte
Então, depois de meio dia mexendo nisso, descobri o seguinte:
Nos vídeos do iPhone de Stanford, um cara da Apple diz que muitas das coisas do UIKit causarão muitos erros se você "transferir" as solicitações de toque (também conhecidas como os dois métodos descritos acima), e você provavelmente não fará com que funcione.
A SOLUÇÃO : é descrita aqui: Interceptando / Hijacking iPhone Touch Events para MKMapView . Basicamente, você "captura" o evento antes que qualquer respondente o receba e o interpreta ali.
fonte
Em Swift 3.0
fonte
Faça do MKMapView uma subvisão de uma visão personalizada e implemente
na visualização personalizada para retornar a si mesmo em vez da subvisualização.
fonte
Obrigado pela pizza e gritos - você me economizou muito tempo.
habilitado para multipleto funcionará esporadicamente.
No final, mudei as visualizações quando precisei capturar o toque (ponto diferente no tempo do que a necessidade de pinchzooms):
fonte
Percebi que você pode rastrear o número e a localização dos toques e obter a localização de cada um em uma visualização:
Alguém mais tentou usar esses valores para atualizar o nível de zoom do mapa? Seria uma questão de registrar as posições de largada e depois as localizações de chegada, calculando a diferença relativa e atualizando o mapa.
Estou brincando com o código básico fornecido por Martin e parece que vai funcionar ...
fonte
Aqui está o que eu juntei, que permite zooms de pinça no simulador (não tentei em um iPhone real), mas acho que seria bom:
A ideia principal é que, se o usuário estiver usando dois dedos, você acompanhe os valores. Eu registro os pontos inicial e final nos pontos iniciais A e B. Então eu registro os pontos de rastreamento atuais e, quando terminar, no touchEnded, posso chamar uma rotina para calcular os comprimentos relativos da linha entre os pontos com os quais começo , e a linha entre o ponto I termina usando simples hipotenusa calc. A proporção entre eles é a quantidade de zoom: eu multiplico a extensão da região por essa quantidade.
Espero que seja útil para alguém.
fonte
Eu peguei a ideia de uma visão transparente "sobreposta", da resposta de MystikSpiral, e funcionou perfeitamente para o que eu estava tentando alcançar; solução rápida e limpa.
Resumindo, eu tinha um UITableViewCell customizado (projetado em IB) com um MKMapView no lado esquerdo e alguns UILabels à direita. Eu queria fazer a célula personalizada para que você pudesse tocá-la em qualquer lugar e isso empurraria um novo controlador de visualização. No entanto, tocar o mapa não passou "para cima" no UITableViewCell até que eu simplesmente adicionei um UIView do mesmo tamanho que a visualização do mapa bem em cima dele (em IB) e tornei seu fundo a 'cor clara' no código ( não acho que você pode definir clearColor em IB ??):
Achei que poderia ajudar outra pessoa; certamente se você deseja obter o mesmo comportamento para uma célula de exibição de tabela.
fonte