どのように遮チのイベントにMKMapViewはUIWebView物?
-
20-08-2019 - |
質問
お使いいただくことによってんでいるのは間違ったもののようにしていく触れる MKMapView
オブジェクトです。私はサブクラス化で作成の以下のクラス:
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface MapViewWithTouches : MKMapView {
}
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event;
@end
の実施:
#import "MapViewWithTouches.h"
@implementation MapViewWithTouches
- (void) touchesBegan:(NSSet *)touches withEvent:(UIEvent *) event {
NSLog(@"hello");
//[super touchesBegan:touches withEvent:event];
}
@end
のようにも見えご利用する場合は、このクラスは、いかなるコンテンツも、コンソール:
MapViewWithTouches *mapView = [[MapViewWithTouches alloc] initWithFrame:self.view.frame];
[self.view insertSubview:mapView atIndex:0];
問い合わせください私が悪いのでしょうか。
解決
最良の方法なんでこれを実現するジェスチャー認識.その他の方法による多くのhackishしたプログラムimperfectly複Appleのコードでは、特にmultitouch.
こちらの私の役割だと思い:実施するジェスチャ認識と防止することはできないことを止めさせることはできませんその他のジェスチャー recognizers.に加え、地図を使用してgestureRecognizerのtouchesBegan,touchesMoved。おサンドウィッチレストラン。
どのように認をタップ内のMKMapView(sans 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
迅速かつ3
let tapInterceptor = WildCardGestureRecognizer(target: nil, action: nil)
tapInterceptor.touchesBeganCallback = {
_, _ in
self.lockedOnUserLocation = false
}
mapView.addGestureRecognizer(tapInterceptor)
WildCardGestureRecognizer.迅速かつ
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
}
}
他のヒント
日本ピザ、screamings、その解決!非常に綺麗!
ピーターを使ったおトリックの上、調整が入って少したしているソリューション事もMKMapViewやるべき仕事もUIWebView
MKTouchAppDelegate.h
#import <UIKit/UIKit.h>
@class UIViewTouch;
@class MKMapView;
@interface MKTouchAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
UIViewTouch *viewTouch;
MKMapView *mapView;
}
@property (nonatomic, retain) UIViewTouch *viewTouch;
@property (nonatomic, retain) MKMapView *mapView;
@property (nonatomic, retain) IBOutlet UIWindow *window;
@end
MKTouchAppDelegate.m
#import "MKTouchAppDelegate.h"
#import "UIViewTouch.h"
#import <MapKit/MapKit.h>
@implementation MKTouchAppDelegate
@synthesize window;
@synthesize viewTouch;
@synthesize mapView;
- (void)applicationDidFinishLaunching:(UIApplication *)application {
//We create a view wich will catch Events as they occured and Log them in the Console
viewTouch = [[UIViewTouch alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
//Next we create the MKMapView object, which will be added as a subview of viewTouch
mapView = [[MKMapView alloc] initWithFrame:CGRectMake(0, 0, 320, 480)];
[viewTouch addSubview:mapView];
//And we display everything!
[window addSubview:viewTouch];
[window makeKeyAndVisible];
}
- (void)dealloc {
[window release];
[super dealloc];
}
@end
UIViewTouch.h
#import <UIKit/UIKit.h>
@class UIView;
@interface UIViewTouch : UIView {
UIView *viewTouched;
}
@property (nonatomic, retain) UIView * viewTouched;
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event;
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event;
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event;
@end
UIViewTouch.m
#import "UIViewTouch.h"
#import <MapKit/MapKit.h>
@implementation UIViewTouch
@synthesize viewTouched;
//The basic idea here is to intercept the view which is sent back as the firstresponder in hitTest.
//We keep it preciously in the property viewTouched and we return our view as the firstresponder.
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
NSLog(@"Hit Test");
viewTouched = [super hitTest:point withEvent:event];
return self;
}
//Then, when an event is fired, we log this one and then send it back to the viewTouched we kept, and voilà!!! :)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Began");
[viewTouched touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Moved");
[viewTouched touchesMoved:touches withEvent:event];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Ended");
[viewTouched touchesEnded:touches withEvent:event];
}
- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Cancelled");
}
@end
いすき!
乾杯
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(handleGesture:)];
tgr.numberOfTapsRequired = 2;
tgr.numberOfTouchesRequired = 1;
[mapView addGestureRecognizer:tgr];
[tgr release];
- (void)handleGesture:(UIGestureRecognizer *)gestureRecognizer
{
if (gestureRecognizer.state != UIGestureRecognizerStateEnded)
return;
CGPoint touchPoint = [gestureRecognizer locationInView:mapView];
CLLocationCoordinate2D touchMapCoordinate = [mapView convertPoint:touchPoint toCoordinateFromView:mapView];
//.............
}
MKMapViewのため、実際の作業溶液は、ジェスチャrecognizationである!
私は、私は、ズームにマップやピンチをドラッグすると、私の場所に地図の中心の更新を停止したかっます。
だから、作成のMapViewにあなたのジェスチャー認識を追加します:
- (void)viewDidLoad {
...
// Add gesture recognizer for map hoding
UILongPressGestureRecognizer *longPressGesture = [[[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAndPinchGesture:)] autorelease];
longPressGesture.delegate = self;
longPressGesture.minimumPressDuration = 0; // In order to detect the map touching directly (Default was 0.5)
[self.mapView addGestureRecognizer:longPressGesture];
// Add gesture recognizer for map pinching
UIPinchGestureRecognizer *pinchGesture = [[[UIPinchGestureRecognizer alloc] initWithTarget:self action:@selector(handleLongPressAndPinchGesture:)] autorelease];
pinchGesture.delegate = self;
[self.mapView addGestureRecognizer:pinchGesture];
// Add gesture recognizer for map dragging
UIPanGestureRecognizer *panGesture = [[[UIPanGestureRecognizer alloc] initWithTarget:self action:@selector(handlePanGesture:)] autorelease];
panGesture.delegate = self;
panGesture.maximumNumberOfTouches = 1; // In order to discard dragging when pinching
[self.mapView addGestureRecognizer:panGesture];
}
/ < UIGestureRecognizerクラスリファレンスを見てA>すべての利用可能なジェスチャー認識を確認します。
私たちは、自己へのデリゲートを定義したので、我々はprotocoleのUIGestureRecognizerDelegateを実装する必要があります:
typedef enum {
MapModeStateFree, // Map is free
MapModeStateGeolocalised, // Map centred on our location
MapModeStateGeolocalisedWithHeading // Map centred on our location and oriented with the compass
} MapModeState;
@interface MapViewController : UIViewController <CLLocationManagerDelegate, UIGestureRecognizerDelegate> {
MapModeState mapMode;
}
@property (nonatomic, retain) IBOutlet MKMapView *mapView;
...
そしてMethodeのgestureRecognizer上書き:gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizerを:同時に複数のジェスチャーを認識できるようにするために、私は理解している場合、右ます:
// Allow to recognize multiple gestures simultaneously (Implementation of the protocole UIGestureRecognizerDelegate)
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
return YES;
}
今私達のジェスチャー認識装置によって呼び出されますmethodesを書きます:
// On map holding or pinching pause localise and heading
- (void)handleLongPressAndPinchGesture:(UIGestureRecognizer *)sender {
// Stop to localise and/or heading
if (sender.state == UIGestureRecognizerStateBegan && mapMode != MapModeStateFree) {
[locationManager stopUpdatingLocation];
if (mapMode == MapModeStateGeolocalisedWithHeading) [locationManager stopUpdatingHeading];
}
// Restart to localise and/or heading
if (sender.state == UIGestureRecognizerStateEnded && mapMode != MapModeStateFree) {
[locationManager startUpdatingLocation];
if (mapMode == MapModeStateGeolocalisedWithHeading) [locationManager startUpdatingHeading];
}
}
// On dragging gesture put map in free mode
- (void)handlePanGesture:(UIGestureRecognizer *)sender {
if (sender.state == UIGestureRecognizerStateBegan && mapMode != MapModeStateFree) [self setMapInFreeModePushedBy:sender];
}
念のために誰かが私のような同じことをやろうとしている:私は、ユーザーがタップ時点でのアノテーションを作成したいです。そのために私はUITapGestureRecognizer
ソリューションを使用します:
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapOnMap:)];
[self.mapView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer setDelegate:self];
- (void)didTapOnMap:(UITapGestureRecognizer *)gestureRecognizer
{
CGPoint point = [gestureRecognizer locationInView:self.mapView];
CLLocationCoordinate2D coordinate = [self.mapView convertPoint:point toCoordinateFromView:self.mapView];
.......
}
しかし、didTapOnMap:
は、私は、注釈にタップするとも呼ばれていたと新しいものが作成されます。解決策は、実装することである。UIGestureRecognizerDelegate
:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch
{
if ([touch.view isKindOfClass:[MKAnnotationView class]])
{
return NO;
}
return YES;
}
あなたはおそらくちょうど好きがのUIWebViewベースのコントロールでそれほど頻繁に行われているタッチをキャッチする透視図をオーバーレイする必要があります。マップビューは、すでにメッセージアプリまで泡立て取得されていないこと...など、マップは、移動中心に、ズームすることができるようにするために、タッチで特別なものの束を行います。
私は考えることができる他の二つの(未テスト)オプションます:
1)IBを介して第1の応答者を辞任し、ファイルの所有者は、タッチに対応できるようにするために、「ファイルの所有者」に設定します。私MKMapViewはNSObjectの、ないのUIView ANSタッチイベントはまだあなたまで伝播されないことがあり、結果を拡張しているため、これが動作すること怪しげます。
2)あなたがトラップしたい場合は、ズームのよう地図状態の変化は、()だけで特定のイベントをリッスンするMKMapViewDelegateプロトコルを実装する場合。私の勘では、これは簡単に(地図の上に透明表示を実現するための短い)、いくつかの相互作用をトラップであなたの最高のショットです。 (map.delegate = self
)マップのデリゲートとしてビューコントローラハウジングMKMapViewを設定することを忘れないでください。
グッドラックます。
私は実験していませんが、MapKitはクラスクラスタの周りに基づいています良いチャンスがありますので、それは難しいと効果がないサブクラスます。
私はMapKitが、彼らはそれに到達する前にタッチイベントをインターセプトできるようにする必要があり、カスタムビューのサブビューを表示することをお勧めしたい。
にその後の半日のろなことから、以下の:
- なんとか見つから挟み込みは無効となります。また双方は、サブクラスMKMapView、上記の方法(遮断します。その結果は同じです。
にスタンフォードiPhone動画、男はAppleによると多くのUIKitうになりま 原因テルのすぐ近くは飲食面では貧弱誤りの場合は"転写"をタッチをご希望の通称を上記の方法、まんが得られます。
の溶液:についてはこちらをご覧下さい: 遮断/ハイジャックiPhoneタッチイベントMKMapView.基本的にはい"キャッチ"のイベントの前に返信がな解釈である。
スイフト3.0での の
import UIKit
import MapKit
class CoordinatesPickerViewController: UIViewController {
@IBOutlet var mapView: MKMapView!
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(clickOnMap))
mapView.addGestureRecognizer(tapGestureRecognizer)
}
@objc func clickOnMap(_ sender: UITapGestureRecognizer) {
if sender.state != UIGestureRecognizerState.ended { return }
let touchLocation = sender.location(in: mapView)
let locationCoordinate = mapView.convert(touchLocation, toCoordinateFrom: mapView)
print("Tapped at lat: \(locationCoordinate.latitude) long: \(locationCoordinate.longitude)")
}
}
MKMapViewにカスタムビューのサブビューを作成し、実装する
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event
カスタムビューでの自己の代わりに、サブビューを返すようにます。
ピザやscreamingsをありがとう - 。あなたは私に多くの時間を保存
散発的に動作しますmultipletouchenabledます。
viewTouch.multipleTouchEnabled = TRUE;
Iタッチ(pinchzoomsを必要とするよりも時間的に異なる時点)を捕捉するために必要なときに最後に、私は、ビューを切り替える
[mapView removeFromSuperview];
[viewTouch addSubview:mapView];
[self.view insertSubview:viewTouch atIndex:0];
私はあなたのタッチの数と位置を追跡し、ビュー内の各位置を得ることができることがわかります:
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Moved %d", [[event allTouches] count]);
NSEnumerator *enumerator = [touches objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
NSLog(@"touch description %f", [value locationInView:mapView].x);
}
[viewTouched touchesMoved:touches withEvent:event];
}
誰にもマップのズームレベルを更新するために、これらの値を使用してみましたていますか?それは相対的な差を計算し、マップを更新し、開始位置を記録する問題で、その後、仕上げの場所になります。
私はマーティンが提供する基本的なコードで遊んでいて、それが動作するように、これが見えます...
ここで私はピンチが(実際のiPhoneで試していません)シミュレータでズームインすることができないこと、一緒に入れ何だが、私は大丈夫だと思います:
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(@"Touch Began %d", [touches count]);
reportTrackingPoints = NO;
startTrackingPoints = YES;
[viewTouched touchesBegan:touches withEvent:event];
}
- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
if ([[event allTouches] count] == 2) {
reportTrackingPoints = YES;
if (startTrackingPoints == YES) {
BOOL setA = NO;
NSEnumerator *enumerator = [[event allTouches] objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
if (! setA) {
startPointA = [value locationInView:mapView];
setA = YES;
} else {
startPointB = [value locationInView:mapView];
}
}
startTrackingPoints = NO;
} else {
BOOL setA = NO;
NSEnumerator *enumerator = [[event allTouches] objectEnumerator];
id value;
while ((value = [enumerator nextObject])) {
if (! setA) {
endPointA = [value locationInView:mapView];
setA = YES;
} else {
endPointB = [value locationInView:mapView];
}
}
}
}
//NSLog(@"Touch Moved %d", [[event allTouches] count]);
[viewTouched touchesMoved:touches withEvent:event];
}
- (void) updateMapFromTrackingPoints {
float startLenA = (startPointA.x - startPointB.x);
float startLenB = (startPointA.y - startPointB.y);
float len1 = sqrt((startLenA * startLenA) + (startLenB * startLenB));
float endLenA = (endPointA.x - endPointB.x);
float endLenB = (endPointA.y - endPointB.y);
float len2 = sqrt((endLenA * endLenA) + (endLenB * endLenB));
MKCoordinateRegion region = mapView.region;
region.span.latitudeDelta = region.span.latitudeDelta * len1/len2;
region.span.longitudeDelta = region.span.longitudeDelta * len1/len2;
[mapView setRegion:region animated:YES];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if (reportTrackingPoints) {
[self updateMapFromTrackingPoints];
reportTrackingPoints = NO;
}
[viewTouched touchesEnded:touches withEvent:event];
}
主なアイデアは、ユーザーが2本の指を使用している場合、あなたが値を追跡することです。 Iは、開始を記録しstartPoints AとBの点を終了すると、次に、私は現在のトラッキングポイントを記録し、そしてIが完了していたとき、touchesEndedに、私は私は開始点の間の線の相対的な長さを計算するルーチンを呼び出すことができ、と私はシンプルな斜辺CALCを使用して終了点の間の線。これらの間の比率は、ズーム量である:私はその分領域スパンを乗算
。それは誰かに便利だと思います。
私はMystikSpiralの答えから、「オーバーレイ」透視図のアイデアを取って、それは私が達成しようとしていた何のために完全に働きました。迅速、かつクリーンな解決策ます。
要するに、私は左手側、右側にいくつかのUILabelsにMKMapViewでカスタム(IBに設計された)のUITableViewCellを持っていました。私はあなたがどこでもそれに触れることができ、これは、新しいビューコントローラをプッシュしますので、カスタムセルを作りたかったです。私は単に(IBで)右のそれの上にマップビューと同じサイズのUIViewのを追加し、それが(コードの「明確な色の」背景だなされるまで、しかしマップをタッチするのUITableViewCellに「アップ」のタッチを通過しませんでしたあなたはIBでclearColorを??)に設定することができないと思います。
dummyView.backgroundColor = [UIColor clearColor];
は、それが他の誰かを助けるかもしれないと思いました。確かにあなたは、テーブルビューのセルに同じ動作を実現したい場合。