如何在mapbox的mapView上检测是否点击了singleTap?

问题描述 投票:7回答:7

iOS上的mapBox地图需求。 (我不是在谈论MKMapView)我们如何检测是否在mapView上点击了singleTap?我需要singleTap仅在地图的空白区域(没有引脚)处理,并且当我点击引脚时调用didSelectAnnotation。

但我在android上发现我们有这样的方法

mapboxMap.setOnMapClickListener(new MapboxMap.OnMapClickListener() {
            public void onMapClick(@NonNull LatLng point) {
                Toast.makeText(getActivity(),"on Tap "+point.getLatitude(),Toast.LENGTH_LONG).show();
            }
        });

以及那个

mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() { ... })将显示注释。

我们在iOS中没有相同的概念吗?

实际问题是在iOS中,当我在Mapbox的mapView上添加singleTapGesture

UITapGestureRecognizer *singleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleSingleTap:)];
[self.mapView addGestureRecognizer:singleTapGesture];

mapbox的mapView的委托方法不会调用。

- (nullable UIView <MGLCalloutView> *)mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id <MGLAnnotation>)annotation;

为了确保委托方法必须调用,那么我不必使用qazxsw poi

这里的情况要么是这个,要么就是这样,但根据我的需要,我需要两者。

期待任何解决方案。谢谢,

ios objective-c mapbox mapbox-gl
7个回答
2
投票

我在这里做了另一个解决方法

我克隆了release-ios-v3.3.0并使用singleTapGesture创建了包,并根据我的需要在Building the SDK中添加了一个委托方法。 MGLMapvViewDelegate.h

在MGLMapView.mm我更新了这样的代码,

-(void)mapView:(MGLMapView *)mapView tapOnNonAnnotationAreaWithPoints:(CGPoint)points

这是在else{ if(self.selectedAnnotation) [self deselectAnnotation:self.selectedAnnotation animated:YES]; else if([self.delegate respondsToSelector:@selector(mapView:tapOnNonAnnotationAreaWithPoints:)]) [self.delegate mapView:self tapOnNonAnnotationAreaWithPoints:tapPoint]; } 方法。

它为我工作,因为我能够检测到非注释区域的单击。后来我将传递的-(void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap 转换为地理坐标,以便我使用新的坐标坐标。

注意

  1. 新创建的库大小约为points,其中下载的库是48.7 MB
  2. 样式不正常,你可以在附加的pic.38.3 MBenter image description here中看到(尝试使用不同的样式URL,但没有一个与之前相同)
  3. 我觉得应用程序性能不足,缩放和平移并不像Mapbox的动态库那样流畅。

我还在探索。 lemme知道你是否想要我去检查/探索。

如果有帮助,请接受这个答案。

谢谢,

快乐的编码。


1
投票

试试swift 3

enter image description here

功能句柄

//determined is Point inner to realm polygons
func determinedInPoligon(point:CLLocationCoordinate2D, poligon:[CLLocationCoordinate2D]) -> Bool {

    var result:Bool = false
    var j = poligon.count - 1

    for i in 0 ..< poligon.count {

        if  (poligon[i].longitude < point.longitude && poligon[j].longitude >= point.longitude || poligon[j].longitude < point.longitude && poligon[i].longitude >= point.longitude) &&
            (poligon[i].latitude + (point.longitude - poligon[i].longitude) / (poligon[j].longitude - poligon[i].longitude) * (poligon[j].latitude - poligon[i].latitude) < point.latitude) {
            result = !result;
        }
        j = i;

    }
    return result
}

func squareFrom(location: CGPoint, radius: Double) -> CGRect {//return rect with CGPoint center and radius
    let length = radius
    return CGRect(x: Double(location.x - CGFloat(length / 2)), y: 
   Double(location.y - CGFloat(length / 2)), width: length, height: length)
} 

或者不准确的方法,但是一个工人;)

func handleTap(_ gesture: UITapGestureRecognizer) {

    // Get the CGPoint where the user tapped.
    let spot = gesture.location(in: mapView)

    let my_features = mapView.visibleFeatures(at: spot)
    let strZoomValue = mapView.zoomLevel > 15 ? "6" : "4"
    //the feature structur object value not equal annotation object
    for value in my_features.enumerated() {// feature items
        if value.element is MGLPointAnnotation  {

            for annot in (mapView.annotations?.enumerated())! { // annotation items
                if annot.element is MGLPointAnnotation {

                    //rounded lat and lng value
                    var arr_cllocation = [CLLocationCoordinate2D]()
                    for cllocation in [(annot.element as! MGLPointAnnotation).coordinate, (value.element as! MGLPointAnnotation).coordinate] {

                        let strLat = String(format: "%."+strZoomValue+"f", cllocation.latitude)
                        let strLon = String(format: "%."+strZoomValue+"f", cllocation.longitude)
                        arr_cllocation.append(
                            CLLocationCoordinate2D(latitude: CLLocationDegrees(strLat)!, longitude: CLLocationDegrees(strLon)!) )
                    }

                    if arr_cllocation.count == 2 &&
                        memcmp(&arr_cllocation[0], &arr_cllocation[1], MemoryLayout<CLLocationCoordinate2D>.size) == 0 {// 0 if equal object
                        // to do custom popup view
                        let instViewPopupLineClass = UINib(nibName: "ViewPopupBase", bundle: nil).instantiate(withOwner: self, options: nil).first as! UIView

                        for objectInst in instViewPopupLineClass.subviews.enumerated() {

                            if objectInst.element is UILabel {
                                let asdasdas = (annot.element as! MGLPointAnnotation).subtitle
                                (objectInst.element as! UILabel).text = asdasdas
                                MyCustomPopup(customView: instViewPopupLineClass, positionXY: spot)
                                break
                            }
                        }
                    }
                }
            } //for end

        }
    }
}

1
投票

子类MGLMapView并委托其'func handleTap(_ gesture: UITapGestureRecognizer) {// Get the CGPoint where the user tapped. let spot = gesture.location(in: mapView) let cllcordinatTap = mapView.convert(spot, toCoordinateFrom: mapView) //for determined zoom scala let deltScalaMap = abs(self.mapView.maximumZoomLevel - self.mapView.zoomLevel) //The large is zoom maps, then smal size is tap location, and vice versa. let checkScalaMap = deltScalaMap == 0 ? 1 : deltScalaMap let _rect = squareFrom(location: CGPoint(x: cllcordinatTap.latitude, y: cllcordinatTap.longitude), radius: 0.00005 * checkScalaMap) for annot in (mapView.annotations?.enumerated())! { if annot.element is MGLPointAnnotation { let _cordinatCurrentAnnotation = (annot.element as! MGLPointAnnotation).coordinate if determinedInPoligon(point: _cordinatCurrentAnnotation, poligon: [CLLocationCoordinate2D(latitude: CLLocationDegrees(_rect.minX), longitude: CLLocationDegrees(_rect.minY)), CLLocationCoordinate2D(latitude: CLLocationDegrees(_rect.maxX), longitude: CLLocationDegrees(_rect.minY)), CLLocationCoordinate2D(latitude: CLLocationDegrees(_rect.maxX), longitude: CLLocationDegrees(_rect.maxY)), CLLocationCoordinate2D(latitude: CLLocationDegrees(_rect.minX), longitude: CLLocationDegrees(_rect.maxY)) ]) { // to do, if tap MGLPointAnnotation, annot.element } } } }

touchesEnded

由于在调用protocol MapViewTapDelegate: class { func mapViewTapped(withTouchLocation touchLocation: CLLocationCoordinate2D) } class MapView: MGLMapView { weak var tapDelegate: MapViewTapDelegate? override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { super.touchesEnded(touches, with: event) guard let touch = touches.first else { return } let touchLocation = convert(touch.location(in: self), toCoordinateFrom: nil) tapDelegate?.mapViewTapped(withTouchLocation: touchLocation) } } 时没有触发touchesEnded,反之亦然,这就是你所需要的。

didSelect annotation

0
投票

我认为方法class ViewController: UIViewController { @IBOutlet weak var mapView: MapView! { didSet { mapView.delegate = self; mapView.tapDelegate = self } } } extension ViewController: MGLMapViewDelegate { func mapView(_ mapView: MGLMapView, didSelect annotation: MGLAnnotation) { print("didSelect annotationWithCoordinate: \(annotation.coordinate)") } } extension ViewController: MapViewTapDelegate { func mapViewTapped(withTouchLocation touchLocation: CLLocationCoordinate2D) { print("mapViewTapped touchLocation: \(touchLocation)") } } 将解决您选择注释的问题。


0
投票

我为你的问题尝试了示例项目,效果很好。

。H

-(void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation

.M

#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
@interface ViewController : UIViewController<MKMapViewDelegate>
@property (strong, nonatomic) IBOutlet MKMapView *mapTapAnnotation;
@end

打印输出结果是

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController


@synthesize mapTapAnnotation;

- (void)viewDidLoad {
 [super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
  [self setMapViewWithAnnnoationPin];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

-(void)setMapViewWithAnnnoationPin
{

  mapTapAnnotation.showsUserLocation = YES;
  mapTapAnnotation.mapType = MKMapTypeHybrid;

  CLLocationCoordinate2D coord = CLLocationCoordinate2DMake(12.900988, 80.227930);

  MKCoordinateSpan span = MKCoordinateSpanMake(0.005,  0.005);
  MKCoordinateRegion region = {coord, span};

  MKPointAnnotation *annotation = [[MKPointAnnotation alloc] init];
  [annotation setCoordinate:coord];
  [annotation setTitle:@"Single Tap"]; //You can set the subtitle too


  [mapTapAnnotation setRegion:region];
  [mapTapAnnotation addAnnotation:annotation];


  UITapGestureRecognizer *tapGesture = [[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(detectSingleTap)];
  tapGesture.numberOfTapsRequired = 1;
  [mapTapAnnotation addGestureRecognizer:tapGesture];
}

-(void)detectSingleTap
{
   NSLog(@"Finded the single tap on map view");
}


 - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"The single tap annotation pin point is - %ld",(long)view.tag);
}

0
投票

在这里,我得到了一些有助于满足我的要求的解决方法。根据我的需要,我可以在mapbox注释标记和地图的空白区域上进行单击检测

我为MGLMapView创建了类别(MGLMapView + EDCMapboxView)并覆盖了触摸方法

Finded the single tap on map view
The single tap annotation pin point is - 0

MGLMapView + EDCMapboxView.h

-touchesBegan:withEvent:
-touchesMoved:withEvent:
-touchesEnded:withEvent:
-touchesCancelled:withEvent:

MGLMapView + EDCMapboxView.m

@protocol EDCMapboxViewDelegate <NSObject>
@optional
- (void)mapboxViewDidCreateNewTicket:(MGLMapView*)mapView;
@end

@interface MGLMapView (EDCMapboxView)

@property (assign, nonatomic) BOOL shouldCreateNewTicket;

@property (weak, nonatomic) id <EDCMapboxViewDelegate> mapboxDelegate;
@end

EDCMapboxViewController.m

@implementation MGLMapView (EDCMapboxView)
@dynamic mapboxDelegate;

#pragma mark -- Accessor
- (BOOL)shouldCreateNewTicket {
    return [objc_getAssociatedObject(self, @selector(shouldCreateNewTicket)) boolValue];
}
- (void)setShouldCreateNewTicket:(BOOL)flag {
    objc_setAssociatedObject(self, @selector(shouldCreateNewTicket), @(flag), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

-(id<EDCMapboxViewDelegate>)mapboxDelegate{
    return objc_getAssociatedObject(self, @selector(mapboxDelegate));
}
- (void)setMapboxDelegate:(id<EDCMapboxViewDelegate>)mapboxDelegate{
    objc_setAssociatedObject(self, @selector(mapboxDelegate), mapboxDelegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

#pragma mark -- Overrided method for UIResponder
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
    NSLog(@"touchesBegan");
}

- (void)touchesMoved:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
    NSLog(@"touchesMoved");
    self.shouldCreateNewTicket = NO;
}

- (void)touchesEnded:(NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
    NSLog(@"touchesEnded");
}

- (void)touchesCancelled:(nullable NSSet<UITouch *> *)touches withEvent:(nullable UIEvent *)event{
    NSLog(@"touchesCancelled");

    [self createNewTicket];
}

- (void)createNewTicket{
    if(self.shouldCreateNewTicket){
        NSLog(@"Allowed to Create New ticket");
        // Tells that tap is on empty area.
        if([self.mapboxDelegate respondsToSelector:@selector(mapboxViewDidCreateNewTicket:)]){
            [self.mapboxDelegate mapboxViewDidCreateNewTicket:self];
        }
    }
    else{
        NSLog(@"Not allowed to create New ticket");
        // Tells tap is on annotation marker.
        self.shouldCreateNewTicket = YES;
    }
}

它对我有用,希望它也会帮助你们。谢谢。


0
投票

这是我如何解决它,你应该得到这个概念。

- (void)viewDidLoad {
    [super viewDidLoad];
    self.mapView.shouldCreateNewTicket = YES;   
    .....
    .......
    ........
}

- (BOOL)mapView:(MGLMapView *)mapView annotationCanShowCallout:(id <MGLAnnotation>)annotation {
    NSLog(@"annotationCanShowCallout");

    // Tells that annotation is tapped, then do not allow to create ticket.
    self.mapView.shouldCreateNewTicket = NO;

    return YES;
}

- (void)mapboxViewDidCreateNewTicket:(MGLMapView*)mapView{
   // Tells that tap is on empty area and not on marker, then allow to create ticket. 
}
© www.soinside.com 2019 - 2024. All rights reserved.