如何启用的MKMapView touchEvents(滚动和平移)的自定义的UIView下面?(Ho

2019-08-16 23:18发布

替代文字http://www.gisnotes.com/wordpress/wp-content/uploads/2009/09/poly.png

概括地说,我试图找出如何在规模上的MKMapView(MapView类)的顶部自定义视图(geometryView)实现的几何形状(点,线和面)。

我所做的是..

  1. 创建DrawMapViewController。 底部工具栏上添加UIBarButtonItems(MAP,PT,LN,PG)。

  2. 当你点击地图按钮,您就可以出锅的地图/变焦。 这使的MapView通过设置geometryView.hidden = YES;

  3. 当任何三个几何按钮被点击,geometryView由geometryView.hidden显示= NO,因而使能touchEvents和绘图从GeometryView.drawRect的方法的几何形状。

层顺序如下:MapView的是geometryView的底部。

-geometryView

-mapView

什么是我的问题吗? 理想的情况下,在“地图”模式,当用户平移和缩放,我希望如果可以显示从geometryView绘图。 但是,当用户点击“地图”,然后geometryView.hidden = YES,从而该图消失。 如果我做geometryView可见的,那么用户与geometryView不MapView的交互,所以没有缩放和平移。

是否有可能在显示自定义的视图来处理下面的自定义视图的MKMapView的touchEvents(平移/缩放)? 任何其他的想法/方法是非常赞赏。

谢谢,

鲁珀特

GeometryView清单:

@synthesize mapview, pinFactory;

- (id)initWithFrame:(CGRect)frame{
    if (self = [super initWithFrame:frame]) {
    }
    return self;
}

- (void)drawRect:(CGRect)rect {
    // Drawing code
    NSLog(@"DrawRect called");

    CGContextRef context = UIGraphicsGetCurrentContext();

    // Drawing lines with a white stroke color
    CGContextSetRGBStrokeColor(context, 1.0, 1.0, 1.0, 1.0);
    // Draw them with a 2.0 stroke width so they are a bit more visible.
    CGContextSetLineWidth(context, 2.0);

    if(pinFactory.geometryState == 2){  //Draw Line

        if( [pinFactory actualPinCount] > 1){

            Pin *pin1 = (Pin *)[[pinFactory pinArray] objectAtIndex:0];
            CGPoint pt1 = pin1.touchLocation;
            CGContextMoveToPoint(context, pt1.x, pt1.y);

            for (int i = 1; i < ([pinFactory actualPinCount]); i++)
            {
                Pin *pin2 = (Pin *)[[pinFactory pinArray] objectAtIndex:i];
                CGPoint pt2 = pin2.touchLocation;
                CGContextAddLineToPoint(context, pt2.x, pt2.y);
            }

            CGContextStrokePath(context);
        }
    }
    else if(pinFactory.geometryState == 3){ //Draw Polygon
        //if there are two points, draw a line first.
        //if there are three points, fill the polygon
        if( [pinFactory actualPinCount] == 2){

            Pin *pin1 = (Pin *)[[pinFactory pinArray] objectAtIndex:0];
            CGPoint pt1 = pin1.touchLocation;
            CGContextMoveToPoint(context, pt1.x, pt1.y);

            Pin *pin2 = (Pin *)[[pinFactory pinArray] objectAtIndex:1];
            CGPoint pt2 = pin2.touchLocation;
            CGContextAddLineToPoint(context, pt2.x, pt2.y);

            CGContextStrokePath(context);
        }
        else if([pinFactory actualPinCount] > 2){

            //fill with a blue color
            CGContextSetRGBFillColor(context, 0.0, 0.0, 1.0, 1.0);

            Pin *pin1 = (Pin *)[[pinFactory pinArray] objectAtIndex:0];
            CGPoint pt1 = pin1.touchLocation;
            CGContextMoveToPoint(context, pt1.x, pt1.y);

            for (int i = 1; i < ([pinFactory actualPinCount]); i++)
            {

                Pin *pin2 = (Pin *)[[pinFactory pinArray] objectAtIndex:i];
                CGPoint pt2 = pin2.touchLocation;
                CGContextAddLineToPoint(context, pt2.x, pt2.y);
            }

            CGContextClosePath(context);

            CGContextDrawPath(context, kCGPathFillStroke);
        }
    }
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
    [self setNeedsDisplay];

    UITouch* aTouch = [touches anyObject];
    location = [aTouch locationInView:self];
    NSLog(@"touchesBegan: x:%f, y:%f", location.x, location.y );

    CLLocationCoordinate2D coordinate = [mapview convertPoint:location toCoordinateFromView:self];

    switch (pinFactory.geometryState) {
        case 1:{
            if( [pinFactory actualPinCount] == 1){
                //[UIView beginAnimations:@"stalk" context:nil];
                //[UIView setAnimationDuration:1];
                //[UIView setAnimationBeginsFromCurrentState:YES];

                Pin *pin = (Pin *)[pinFactory getObjectAtIndex:0];
                [mapview removeAnnotation:pin];
                [pinFactory removeObject:pin];

                Pin *newPin = [[Pin alloc] initWithCoordinate:coordinate initLocation:location withTitle:@"My Pin"];
                [pinFactory addObject:newPin];
                [mapview addAnnotation:newPin];

                [newPin release];

                //[UIView commitAnimations];
            }
            else{
                //Lets add a new pin to the geometry
                Pin *pin = [[Pin alloc] initWithCoordinate:coordinate initLocation:location withTitle:@"My Pin"];
                [pinFactory addObject:pin];
                [mapview addAnnotation:pin];

                [pin release];
            }
            break;
        }
        case 2:{
            //Lets add a new pin
            Pin *pin = [[Pin alloc] initWithCoordinate:coordinate initLocation:location withTitle:@"My Pin"];
            [pinFactory addObject:pin];
            [mapview addAnnotation:pin];

            [pin release];
            [self setNeedsDisplay];

            break;
        }
        case 3:{
            //Lets add a new pin
            Pin *pin = [[Pin alloc] initWithCoordinate:coordinate initLocation:location withTitle:@"My Pin"];
            [pinFactory addObject:pin];
            [mapview addAnnotation:pin];

            [pin release];
            [self setNeedsDisplay];

            break;
        }
        default:
            break;
    }
}


- (void)dealloc {
    [super dealloc];
}


@end

DrawMapViewController清单:

#import "DrawMapViewController.h"
#import "Pin.h"

@implementation DrawMapViewController

@synthesize mapview, mapBarButton, pointBarButton, lineBarButton, polygonBarButton, geometryView;

/*  State represents state of the map
 *  0 = map
 *  1 = point
 *  2 = line
 *  3 = polygon
 */

// The designated initializer. Override to perform setup that is required before the view is loaded.
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
        // Custom initialization
        self.title = @"Map";
    }
    return self;
}


// Implement viewDidLoad to do additional setup after loading the view, typically from a nib.
- (void)viewDidLoad {
    [super viewDidLoad];
    mapview.mapType = MKMapTypeSatellite;


    NSMutableArray *pinArray = [[NSMutableArray alloc] initWithObjects:nil];
    pinFactory = [[PinFactory alloc] initWithArray:pinArray]; 
    pinFactory.map = mapview;
    [pinArray release];

    geometryView = [[GeometryView alloc] initWithFrame:CGRectMake(0.0f, 0.0f, 320.0f, 372.0f)];
    geometryView.pinFactory = pinFactory;
    geometryView.mapview = mapview;
    geometryView.backgroundColor = [UIColor clearColor];
    [self.view addSubview:geometryView];

    [self changeButtonAndViewState:0];
}


/*
// Override to allow orientations other than the default portrait orientation.
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
    // Return YES for supported orientations
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/

- (void)didReceiveMemoryWarning {
    // Releases the view if it doesn't have a superview.
    [super didReceiveMemoryWarning];

    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidUnload {
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}


- (void)dealloc {
    [mapBarButton release];
    [pointBarButton release];
    [lineBarButton release];
    [polygonBarButton release];

    [super dealloc];
}

- (IBAction)mapBarButtonPressed{
    NSLog(@"mapBarButtonPressed");
    [self changeButtonAndViewState:0];
}

- (IBAction)pointBarButtonPressed{
    NSLog(@"pointBarButtonPressed");
    [self changeButtonAndViewState:1];

    if( [pinFactory actualPinCount] > 0){
        [self resetGeometry];
    }   
}

- (IBAction)lineBarButtonPressed{
    NSLog(@"lineBarButtonPressed");

    if( [pinFactory actualPinCount] > 0){
        [self resetGeometry];
    }

    [self changeButtonAndViewState:2];
}

- (IBAction)polygonBarButtonPressed{
    NSLog(@"polygonBarButtonPressed");

    if( [pinFactory actualPinCount] > 0){
        [self resetGeometry];
    }

    [self changeButtonAndViewState:3];
}

- (void)resetGeometry{
    NSLog(@"resetting geometry.. deleting all pins");
    [mapview removeAnnotations:[pinFactory pinArray]];

    NSMutableArray *array = [pinFactory pinArray];
    [array removeAllObjects];

    [geometryView setNeedsDisplay];
}

- (void)changeButtonAndViewState:(int)s{
    [pinFactory setGeometryState:s];

    mapBarButton.style = UIBarButtonItemStyleBordered;
    pointBarButton.style = UIBarButtonItemStyleBordered;
    lineBarButton.style = UIBarButtonItemStyleBordered;
    polygonBarButton.style = UIBarButtonItemStyleBordered;

    pointBarButton.enabled = YES;
    lineBarButton.enabled = YES;
    polygonBarButton.enabled = YES;

    switch ([pinFactory geometryState]) {
        case 0:{
            mapBarButton.style = UIBarButtonItemStyleDone;
            geometryView.hidden = YES;
            break;
        }
        case 1:{
            pointBarButton.enabled = NO;

            pointBarButton.style = UIBarButtonItemStyleDone;

            geometryView.hidden = NO;
            break;
        }
        case 2:{
            lineBarButton.enabled = NO;

            lineBarButton.style = UIBarButtonItemStyleDone;

            geometryView.hidden = NO;
            break;
        }
        case 3:{
            polygonBarButton.enabled = NO;

            polygonBarButton.style = UIBarButtonItemStyleDone;

            geometryView.hidden = NO;

            break;
        }
        default:
            break;
    }
}

-(void)mapView:(MKMapView *)mapView regionDidChangeAnimated:(BOOL)animate{
    NSLog(@"regionDidChangeAnimated");
}

@end

Answer 1:

嘿,我看到没有人回答你,我只是想出了如何做到这一点。 不幸的是你无法拦截事件,并将其转发到的MapView所以像

@interface MapOverlay
   MKMapView* map;
@end

@implementation
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
   // Do my stuff
   foo();
   bar();
   // Forward to the map
   [map touchesBegan....];
}
@end

这是你想要做什么,但它不会工作。 出于某种原因,你不能截取地图的事件,也可以做反向和继承的MKMapView和重载它的触摸方式。 我发现这样做的唯一方法是如下。

创建MapOverlay视图,将其设置为透明背景和禁用触摸到它。 此叠加在您的MKMapView的顶部。 然后执行以下

子类的UIWindow与自定义类,将所有触摸转发给您的覆盖,无论是处理逻辑“如果叠加不隐藏,再向前”,或在覆盖本身保持状态。 反正它看起来像这样

@implementation CustomWindow

- (void)sendEvent:(UIEvent*)event
{
   [super sendEvent:event];
   // Forward the event to the overlay
}

当您将事件转发到覆盖,您首先检查触摸是你的MapView的区域内,然后找出什么类型的触摸它们,然后调用您的覆盖正确的触摸方法。

祝好运!



Answer 2:

我知道这个答案可能来得太迟,但我会采取刺伤反正那些(如我)谁以前也遇到过这个问题,以及受益。

该的MKMapView类的触摸事件都由一个UIScrollView内部处理。 您可以通过使一个的MKMapView自定义的UIView的子视图,并提供您的自定义涉及在自定义视图的方法捕获此滚动视图的事件。

诀窍是跟踪由的MKMapView使用的的UIScrollView的。 要做到这一点,我推翻了“则hitTest”方法,它返回的“自我”,我认为这意味着自定义视图应该处理的触摸事件。

此外,则hitTest方法获取的MKMapView的UIScrollView的。 在我的自定义的UIView我把它叫做“echo_to”,因为事件再回荡到的UIScrollView,使地图的工作,因为它一般不会。


- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {

    //  Get the UIView (in this case, a UIScrollView) that
    //  would ordinarily handle the events
    echo_to = [super hitTest:point withEvent:event];

    //  But let it be known we'll handle them instead.
    return self;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {

    NSLog(@"Touches Began");
    //  add your custom annotation behavior here
    [echo_to touchesBegan:touches withEvent:event];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {

    NSLog(@"Touches moved");
    //  add your custom annotation behavior here
    [echo_to touchesMoved:touches withEvent:event];
}

祝您好运。



Answer 3:

根据您的geometryView的复杂性,你可以使用一个注解视图中绘制它。

这样做的缺点的方法是,认为不会与地图比例尺(虽然你可以使用mapView:regionDidChangeanimated:委托方法来缩放后重绘),但是它会与平移地图。



Answer 4:

因为你并不需要用户能够挖掘的注释,或捏和缩放地图的则hitTest技巧的伟大工程只要。 这些都不是能够被转发。



文章来源: How to enable touchEvents (scroll and pan) in MKMapview below a custom UIView?