2016-06-28 24 views
6

Richiesto su iOS per mappa mapBox. (Non sto parlando di MKMapView) come possiamo rilevare se SingleTap è stato toccato o annotazione su mapView? Ho bisogno che singleTap venga gestito solo su un'area vuota della mappa (senza pin), e ha fatto sì che SelectAnnotation chiamasse quando tocco su un pin.come posso rilevare se è stato toccato singleTap o annotazione su mapView di mapbox?

Ma ho trovato su Android abbiamo metodo come questo

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

e insieme a questo

mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() { ... }) visualizzerà l'annotazione.

Non abbiamo lo stesso tipo di concetto in iOS?

Il problema reale è in iOS è, quando aggiungo singleTapGesture su MapView di Mapbox

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

il metodo delegato di MapView di mapbox non chiamerà.

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

per assicurarsi che il metodo delegato deve chiamare, quindi non devo usare singleTapGesture

Qui la situazione è questo o quello, ma come per me bisogno avevo bisogno di entrambe le cose.

In attesa di qualsiasi soluzione. Grazie,

+0

INASIR Mostrami la tua codifica completa – user3182143

risposta

0

Penso che il metodo -(void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id<MGLAnnotation>)annotation risolverà il problema per la selezione dell'annotazione.

+0

'- (void) mapView: (MGLMapView *) mapView didSelectAnnotation: (id ) annotation funzionerà solo quando callout tappato, ma quando aggiungo' tapGesture' il su mapView none none del metodo delegato funziona. Nel mio caso ho bisogno sia di 'tapGesture' che di' delegate' chiamate – iNasir

0

Ho provato un progetto di esempio per la tua domanda e funziona bene.

.h

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

.m

#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); 
} 

I risultati di output stampati sono

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

Grazie, apprezzo il tuo aiuto, ma nel mio caso MKMapView non è usato, la sua MGLMapView (mapbox) – iNasir

+0

Carica la tua codifica completa – user3182143

+0

applica lo stesso codice per MGLMapView – user3182143

0

Qui ho avuto qualche soluzione che ha permesso di lavorare con il mio requisito. Come per il mio bisogno io sono in grado di ottenere il rilevamento semplice tocco su entrambi mapbox marcatore di annotazione e così come sulla un'area vuota della mappa

ho creato categoria per MGLMapView, (MGLMapView + EDCMapboxView) e le sostituzioni i metodi di contatto

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

MGLMapView + EDCMapboxView.h

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

@interface MGLMapView (EDCMapboxView) 

@property (assign, nonatomic) BOOL shouldCreateNewTicket; 

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

MGLMapView + EDCMapboxView.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; 
    } 
} 

EDCMapboxViewController.m

- (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. 
} 

Ha funzionato per me, spero che vi aiuterà a ragazzi pure. Grazie.

+0

Qui il flag 'shouldCreateNewTicket' rileva la differenza tra ** tocca sull'area vuota ** e ** tocca sul marker **. – iNasir

+0

Assicurarsi di non finire con la creazione del ciclo di conservazione. Aggiorna ** categoria MGLMapView + EDCMapboxView.m ** con 'OBJC_ASSOCIATION_ASSIGN' invece di' OBJC_ASSOCIATION_RETAIN_NONATOMIC' – iNasir

2

ho fatto un'altra soluzione qui

ho clonato i rilascio-IO-v3.3.0 e pacchetti creati utilizzando Building the SDK e ha aggiunto un metodo delegato in MGLMapvViewDelegate.h come per il mio bisogno di qualcosa di simile. -(void)mapView:(MGLMapView *)mapView tapOnNonAnnotationAreaWithPoints:(CGPoint)points

e MGLMapView.mm ho aggiornato il codice del genere,

else{ 
if(self.selectedAnnotation) 
     [self deselectAnnotation:self.selectedAnnotation animated:YES]; 
else if([self.delegate respondsToSelector:@selector(mapView:tapOnNonAnnotationAreaWithPoints:)]) 
     [self.delegate mapView:self tapOnNonAnnotationAreaWithPoints:tapPoint]; 
} 

che è in -(void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap metodo.

Funziona per me, poiché sono in grado di rilevare un singolo tocco nell'area non di annotazione. più tardi converto il passato a points in coordinate geografiche, in modo da lavorare con coordinate appena toccate.

Nota

  1. dimensione nuova libreria creata è di circa 48.7 MB dove come biblioteca scaricato era 38.3 MB.
  2. Lo stile non funziona correttamente, è possibile vedere nella foto allegata. enter image description hereenter image description here (Provato con URL di stile diverso ma nessuno di esso è uguale al precedente)
  3. Mi sento privo di prestazioni dell'app, zoom e panoramica non sono fluidi come la libreria dinamica fornita da ragazzi di Mapbox.

Sto ancora esplorando. fammi sapere se vuoi che controlli/esplori

Si prega di accettare questa risposta, se è utile.

Grazie,

Coding Felice.

0

Ecco come ho risolto, si dovrebbe ottenere il concetto.

func onMapSingleTapped(recognizer: UITapGestureRecognizer) 
{ 
    let viewLocation: CGPoint = recognizer.locationInView(map) 

    // check if any annotations are hit 
    if(map.annotations != nil) 
    { 
     for annotation in map.annotations! 
     { 
      if(annotation.isKindOfClass(MapCheckInAnnotation)) 
      { 
       let pin: MapCheckInAnnotation = annotation as! MapCheckInAnnotation 

       if let pinView = pin.view 
       { 
        print("pinview \(pinView.frame.origin)") 

        // check if hit pin instead of just map 
        if(viewLocation.x >= pinView.frame.origin.x && viewLocation.x < pinView.frame.origin.x + pinView.frame.width) 
        { 
         if(viewLocation.y >= pinView.frame.origin.y && viewLocation.y < pinView.frame.origin.y + pinView.frame.height) 
         { 
          mapView(map, didSelectAnnotationView: pinView) 
          return 
         } 
        } 
       } 
      } 
     } 
    } 

    // nope, no annotations were clicked 
    let mapLocation: CLLocationCoordinate2D = map.convertPoint(viewLocation, toCoordinateFromView: map) 

    print("onMapSingleTapped \(mapLocation)") 

} 
1

Prova rapida 3

//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) 
} 

funzione maniglia

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 

     } 
    } 
} 

O non metodo preciso, ma un lavoratore;)

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 

      } 
     } 
    } 
}