MKMapView cacher la barre de navigation sur le robinet comme dans l'application photo sans perdre la fonctionnalité de MKMapView
-
27-10-2019 - |
Question
Je voudrais cacher et afficher la barre de navigation sur le robinet comme celui de l'application de photos Mais sans perdre la fonctionnalité du MKMapView. l'utilisateur doit toujours être en mesure de taper deux fois pour zoomer, pincer et zoomer et être en mesure de sélectionner des annotations.
Je l'ai essayé avec:
UITapGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(hideBar:)];
[self.myMKMapView addGestureRecognizer:tapRec];
[tapRec release];
Mais l'utilisateur ne peut sélectionner des annotations plus! Et elle a aussi des peaux double robinets.
Toutes les idées?
La solution
Je sais, il est presque exactement un an trop tard, mais j'espère que quelqu'un peut faire un bon usage de celui-ci. Voici comment je l'ai fait, basé sur @ réponse de Cocoanetics:
BOOL mapReceivedDoubleTap;
...
UITapGestureRecognizer *tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(didTapMap:)];
[tapGestureRecognizer setDelegate:self];
[_mapView addGestureRecognizer:tapGestureRecognizer];
[tapGestureRecognizer release];
...
// ignore annotations
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
return (![[touch view] isKindOfClass:[MKAnnotationView class]]);
}
// take care of double taps for zoom
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer {
if([otherGestureRecognizer isKindOfClass:[UITapGestureRecognizer class]]) {
UITapGestureRecognizer *tr = (UITapGestureRecognizer *)otherGestureRecognizer;
if(tr.numberOfTapsRequired == 2)
mapReceivedDoubleTap = YES;
}
return NO;
}
- (void)didTapMap:(UITapGestureRecognizer *)tapGestureRecognizer {
mapReceivedDoubleTap = NO;
// hide/show on delay
dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, .2f * NSEC_PER_SEC);
dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
if(!mapReceivedDoubleTap)
[self.navigationController setNavigationBarHidden:!self.navigationController.navigationBarHidden animated:YES];
});
}
Swift
import MapKit
class MapViewController: UIViewController, UIGestureRecognizerDelegate {
@IBOutlet weak var myMapView: MKMapView!
var mapReceivedDoubleTap = false
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MapViewController.didTapMap(_:)))
tapGestureRecognizer.delegate = self
myMapView.addGestureRecognizer(tapGestureRecognizer)
}
// ignore annotations
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldReceiveTouch touch: UITouch) -> Bool {
return !touch.isKindOfClass(MKAnnotationView)
}
// take care of double taps for zoom
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer,
shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
if otherGestureRecognizer.isKindOfClass(UITapGestureRecognizer) {
let tr = otherGestureRecognizer as! UITapGestureRecognizer
if tr.numberOfTapsRequired == 2 {
mapReceivedDoubleTap = true
}
}
return false
}
func didTapMap(gestureRecognizer: UIGestureRecognizer) {
mapReceivedDoubleTap = false
// hide/show on delay
let popTime = dispatch_time(DISPATCH_TIME_NOW, Int64(0.2 * Double(NSEC_PER_SEC)))
dispatch_after(popTime, dispatch_get_main_queue(), {
if !self.mapReceivedDoubleTap {
self.navigationController?.setNavigationBarHidden(!(self.navigationController?.navigationBarHidden)!, animated: true)
}
})
}
}
Autres conseils
vous avez probablement besoin de mettre en œuvre la méthode de délégué pour ce geste de reconnaissance pour détecter simultanément que celui sur le MKMapView. Ensuite, vous devez effectuer votre masquer / afficher un retard et si une annotation vous obtient sélectionnée devez annuler cette opération.
Sinon, vous pouvez faire un hitTest dans la méthode déléguée qui vous permet d'éviter de toucher d'être livré à votre geste si la vue est un coup MKAnnotationView.
Vous pouvez dire à votre geste de reconnaissance pour déclencher que si chaque geste de reconnaissance de la carte échouent.
UITapGestureRecognizer* tapRec = [[UITapGestureRecognizer alloc]
initWithTarget:self action:@selector(hideBar:)];
for (UIGestureRecognizer recognizer in self.myMKMapView.gestureRecognizers) {
[tapRec requireGestureRecognizerToFail:recognizer];
}
[self.myMKMapView addGestureRecognizer:tapRec];
[tapRec release];
Je ne sais pas c'est un gestureRecognizer qui gère l'annotation cependant. Devinez vous devez essayer.
Vous pouvez empêcher un simple clic de reconnaissance geste de voler le double-clic l'un avec ce code:
self.singleTap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap:)];
singleTap.numberOfTapsRequired = 1;
for (UIGestureRecognizer* recognizer in self.mapView.gestureRecognizers) {
if([recognizer isKindOfClass: [UITapGestureRecognizer class]] && ((UITapGestureRecognizer*)recognizer).numberOfTapsRequired == 2) {
[singleTap requireGestureRecognizerToFail:recognizer];
}
}
[self.mapView addGestureRecognizer:self.singleTap];
Can peut l'empêcher de voler d'autres gestes de la même manière.