6 votes

Comment puis-je détecter si singleTap a été tapé ou annotation sur mapView de mapbox?

Exigence sur iOS pour la carte MapBox. (Je ne parle pas de MKMapView) Comment pouvons-nous détecter si un singleTap a été effectué ou une annotation sur la mapView ? J'ai besoin que le singleTap soit géré uniquement sur une zone vide de la carte (sans broches), et didSelectAnnotation soit appelé lorsque je tape sur une broche.

Mais j'ai trouvé sur Android une méthode comme celle-ci

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

et en plus de cela

mapboxMap.setInfoWindowAdapter(new MapboxMap.InfoWindowAdapter() { ... }) affichera l'annotation.

N'avons-nous pas le même genre de concept sur iOS ?

Le véritable problème sur iOS est que, lorsque j'ajoute singleTapGesture sur mapView de Mapbox

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

la méthode déléguée de mapView de mapbox ne sera pas appelée.

- (nullable UIView  *)mapView:(MGLMapView *)mapView calloutViewForAnnotation:(id )annotation;

pour garantir que la méthode déléguée soit appelée, alors je n'ai pas à utiliser singleTapGesture

Ici, la situation est soit ceci, soit cela, mais selon moi, j'avais besoin des deux.

En attente de toute solution. Merci,

2voto

iNasir Points 332

J'ai trouvé une autre solution ici

J'ai cloné le release-ios-v3.3.0 et créé un package en utilisant Building the SDK et ajouté une méthode de délégué dans MGLMapvViewDelegate.h selon mes besoins quelque chose comme ça. -(void)mapView:(MGLMapView *)mapView tapOnNonAnnotationAreaWithPoints:(CGPoint)points

et dans MGLMapView.mm j'ai mis à jour le code comme suit,

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

qui se trouve dans la méthode -(void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap.

Cela fonctionne pour moi, car je suis capable de détecter un tap simple sur une zone non annotée. plus tard, je convertis les points passés en coordonnées géographiques, afin de travailler avec la nouvelle coordonnée tapée.

Remarque

  1. La taille de la bibliothèque nouvellement créée est d'environ 48,7 Mo tandis que la bibliothèque téléchargée était de 38,3 Mo.
  2. Le style ne fonctionne pas correctement, vous pouvez le voir sur l'image ci-jointe. description de l'imagedescription de l'image (J'ai essayé avec différentes URL de style mais rien ne correspond à l'original)
  3. Je trouve un manque de performances dans l'application, le zoom et le défilement ne sont pas aussi fluides que la bibliothèque dynamique fournie par les gens de Mapbox.

Je continue d'explorer. Fais-moi savoir si tu veux que je vérifie/explore quelque chose.

Veuillez accepter cette réponse si elle est utile.

Merci,

Code heureux.

1voto

amiron Points 359

Essayez swift 3

// déterminé est Point interne aux polygones du royaume
func déterminéDansPoligon(point: CLLocationCoordinate2D, poligon: [CLLocationCoordinate2D]) -> Bool {

    var résultat: 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) {
            résultat = !résultat;
        }
        j = i;

    }
    return résultat
}

func carréDepuis(emplacement: CGPoint, rayon: Double) -> CGRect {//retourner un rectangle avec le centre CGPoint et le rayon
    let longueur = rayon
    return CGRect(x: Double(emplacement.x - CGFloat(longueur / 2)), y: Double(emplacement.y - CGFloat(longueur / 2)), width: longueur, height: longueur)
} 

fonction de manipulation

func manipulerAppui(_ geste: UITapGestureRecognizer) {

    // Obtenez le CGPoint où l'utilisateur a appuyé.
    let spot = geste.location(in: mapView)

    let mes_fonctionnalités = mapView.featuresVisibles(at: spot)
    let strValeurZoom = mapView.zoomLevel > 15 ? "6" : "4"
    //l'objet de structure de fonctionnalité n'est pas égal à l'objet d'annotation
    for valeur in mes_fonctionnalités.enumerated() {// éléments de fonctionnalité
        if valeur.element is MGLPointAnnotation  {

            for annot in (mapView.annotations?.enumerated())! { // éléments d'annotation
                if annot.element is MGLPointAnnotation {

                    //valeur lat et lng arrondie
                    var arr_cllocation = [CLLocationCoordinate2D]()
                    for cllocation in [(annot.element as! MGLPointAnnotation).coordinate, (valeur.element as! MGLPointAnnotation).coordinate] {

                        let strLat = String(format: "%."+strValeurZoom+"f", cllocation.latitude)
                        let strLon = String(format: "%."+strValeurZoom+"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.size) == 0 {// 0 si objet égal
                        // à faire vue contextuelle personnalisée
                        let instClasseVuePopupLigne = UINib(nibName: "ViewPopupBase", bundle: nil).instantiate(withOwner: self, options: nil).first as! UIView

                        for objectInst in instClasseVuePopupLigne.subviews.enumerated() {

                            if objectInst.element is UILabel {
                                let asdasdas = (annot.element as! MGLPointAnnotation).subtitle
                                (objectInst.element as! UILabel).text = asdasdas
                                MaVueContextuellePersonnalisée(customView: instClasseVuePopupLigne, positionXY: spot)
                                break
                            }
                        }
                    }
                }
            } //fin pour

        }
    }
}

OU méthode peu précise, mais fonctionnelle ;)

func manipulerAppui(_ geste: UITapGestureRecognizer) {// Obtenez le CGPoint où l'utilisateur a appuyé.

    let spot = geste.location(in: mapView)
    let cllcordinatAppui = mapView.convert(spot, toCoordinateFrom: mapView)
                 //pour déterminer l'échelle de zoom
            let  deltScalaCarte = abs(self.mapView.maximumZoomLevel - self.mapView.zoomLevel) 
           //Plus grande est la carte de zoom, plus petite est la taille du clic, et inversement.
            let checkScalaCarte = deltScalaCarte == 0 ? 1 : deltScalaCarte
            let _rect = carréDepuis(emplacement: CGPoint(x: cllcordinatAppui.latitude, y: cllcordinatAppui.longitude), rayon: 0.00005 * checkScalaCarte)
  for annot in (mapView.annotations?.enumerated())! {

       if annot.element is MGLPointAnnotation {
          let _cordinateAnnotationActuelle = (annot.element as! MGLPointAnnotation).coordinate

          if  déterminéDansPoligon(point: _cordinateAnnotationActuelle, 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))
          ]) {

              // à faire, si tap MGLPointAnnotation, annot.element
          }
      }
  }
}

1voto

IT Gypsy Points 222

Sous-classe MGLMapView et délègue son touchesEnded.

protocol MapViewTapDelegate: class {

    func mapViewTapped(withTouchLocation touchLocation: CLLocationCoordinate2D)
}

class MapView: MGLMapView {

    weak var tapDelegate: MapViewTapDelegate?

    override func touchesEnded(_ touches: Set, 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)
    }

}

Comme touchesEnded n'est pas déclenché lorsque didSelect annotation est appelé et vice versa, voici ce dont vous avez besoin.

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

}

0voto

Stefan Points 893

Je pense que la méthode -(void)mapView:(MGLMapView *)mapView didSelectAnnotation:(id)annotation résoudra votre problème de sélection d'annotation.

0voto

user3182143 Points 1

J'ai essayé le projet d'exemple pour votre question et ça fonctionne bien.

.h

#import 
#import 
@interface ViewController : UIViewController
@property (strong, nonatomic) IBOutlet MKMapView *mapTapAnnotation;
@end

.m

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize mapTapAnnotation;

- (void)viewDidLoad {
 [super viewDidLoad];
// Faire toute configuration supplémentaire après le chargement de la vue, généralement à partir d'un nib.
  [self setMapViewWithAnnnoationPin];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Libérer toute resource qui peut être recréée.
}

-(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"]; //Vous pouvez aussi définir le sous-titre

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

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

-(void)detectSingleTap
{
   NSLog(@"Trouvé le simple clic sur la carte");
}

 - (void)mapView:(MKMapView *)mapView didSelectAnnotationView:(MKAnnotationView *)view
{
    NSLog(@"Le point d'annotation du simple clic est - %ld",(long)view.tag);
}

Les résultats de sortie imprimés sont

Trouvé le simple clic sur la carte
Le point d'annotation du simple clic est - 0

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X