diff options
author | Justin R. Miller <incanus@codesorcery.net> | 2015-03-27 11:12:50 -0700 |
---|---|---|
committer | Justin R. Miller <incanus@codesorcery.net> | 2015-03-27 11:12:50 -0700 |
commit | 215a7c4b2b1222f953efaf814041253b1a561725 (patch) | |
tree | a02532ff052e2717adddfa11c9f9698db9b39f2b | |
parent | 2822dd5b623e2d12469398a49d4b019645d0d47e (diff) | |
download | qtlocation-mapboxgl-215a7c4b2b1222f953efaf814041253b1a561725.tar.gz |
only recognize the end state of single taps
-rw-r--r-- | platform/ios/MGLMapView.mm | 175 |
1 files changed, 89 insertions, 86 deletions
diff --git a/platform/ios/MGLMapView.mm b/platform/ios/MGLMapView.mm index 5bf981bda3..200fb02fa7 100644 --- a/platform/ios/MGLMapView.mm +++ b/platform/ios/MGLMapView.mm @@ -743,124 +743,127 @@ mbgl::DefaultFileSource *mbglFileSource = nullptr; - (void)handleSingleTapGesture:(UITapGestureRecognizer *)singleTap { - [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap]; - - CGPoint tapPoint = [singleTap locationInView:self]; - - if (self.userLocationVisible && ! [self.selectedAnnotation isEqual:self.userLocation]) + if (singleTap.state == UIGestureRecognizerStateEnded) { - CGRect userLocationRect = CGRectMake(tapPoint.x - 15, tapPoint.y - 15, 30, 30); + [self trackGestureEvent:MGLEventGestureSingleTap forRecognizer:singleTap]; + + CGPoint tapPoint = [singleTap locationInView:self]; - if (CGRectContainsPoint(userLocationRect, [self convertCoordinate:self.userLocation.coordinate toPointToView:self])) + if (self.userLocationVisible && ! [self.selectedAnnotation isEqual:self.userLocation]) { - [self selectAnnotation:self.userLocation animated:YES]; - return; - } - } + CGRect userLocationRect = CGRectMake(tapPoint.x - 15, tapPoint.y - 15, 30, 30); - // tolerances based on touch size & typical marker aspect ratio - CGFloat toleranceWidth = 40; - CGFloat toleranceHeight = 60; + if (CGRectContainsPoint(userLocationRect, [self convertCoordinate:self.userLocation.coordinate toPointToView:self])) + { + [self selectAnnotation:self.userLocation animated:YES]; + return; + } + } - // setup a recognition area weighted 2/3 of the way above the point to account for average marker imagery - CGRect tapRect = CGRectMake(tapPoint.x - toleranceWidth / 2, tapPoint.y - 2 * toleranceHeight / 3, toleranceWidth, toleranceHeight); - CGPoint tapRectLowerLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y + tapRect.size.height); - CGPoint tapRectUpperLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y); - CGPoint tapRectUpperRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y); - CGPoint tapRectLowerRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y + tapRect.size.height); + // tolerances based on touch size & typical marker aspect ratio + CGFloat toleranceWidth = 40; + CGFloat toleranceHeight = 60; - // figure out what that means in coordinate space - CLLocationCoordinate2D coordinate; - mbgl::LatLngBounds tapBounds; + // setup a recognition area weighted 2/3 of the way above the point to account for average marker imagery + CGRect tapRect = CGRectMake(tapPoint.x - toleranceWidth / 2, tapPoint.y - 2 * toleranceHeight / 3, toleranceWidth, toleranceHeight); + CGPoint tapRectLowerLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y + tapRect.size.height); + CGPoint tapRectUpperLeft = CGPointMake(tapRect.origin.x, tapRect.origin.y); + CGPoint tapRectUpperRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y); + CGPoint tapRectLowerRight = CGPointMake(tapRect.origin.x + tapRect.size.width, tapRect.origin.y + tapRect.size.height); - coordinate = [self convertPoint:tapRectLowerLeft toCoordinateFromView:self]; - tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + // figure out what that means in coordinate space + CLLocationCoordinate2D coordinate; + mbgl::LatLngBounds tapBounds; - coordinate = [self convertPoint:tapRectUpperLeft toCoordinateFromView:self]; - tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + coordinate = [self convertPoint:tapRectLowerLeft toCoordinateFromView:self]; + tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); - coordinate = [self convertPoint:tapRectUpperRight toCoordinateFromView:self]; - tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + coordinate = [self convertPoint:tapRectUpperLeft toCoordinateFromView:self]; + tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); - coordinate = [self convertPoint:tapRectLowerRight toCoordinateFromView:self]; - tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); + coordinate = [self convertPoint:tapRectUpperRight toCoordinateFromView:self]; + tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); - // query for nearby annotations - std::vector<uint32_t> nearbyAnnotations = mbglMap->getAnnotationsInBounds(tapBounds); + coordinate = [self convertPoint:tapRectLowerRight toCoordinateFromView:self]; + tapBounds.extend(mbgl::LatLng(coordinate.latitude, coordinate.longitude)); - int32_t newSelectedAnnotationID = -1; + // query for nearby annotations + std::vector<uint32_t> nearbyAnnotations = mbglMap->getAnnotationsInBounds(tapBounds); - if (nearbyAnnotations.size()) - { - // there is at least one nearby annotation; select one - // - // first, sort for comparison and iteration - std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); + int32_t newSelectedAnnotationID = -1; - if (nearbyAnnotations == self.annotationsNearbyLastTap) + if (nearbyAnnotations.size()) { - // the selection candidates haven't changed; cycle through them - if (self.selectedAnnotation && - [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] - objectForKey:MGLAnnotationIDKey] unsignedIntValue] == self.annotationsNearbyLastTap.back()) - { - // the selected annotation is the last in the set; cycle back to the first - // note: this could be the selected annotation if only one in set - newSelectedAnnotationID = self.annotationsNearbyLastTap.front(); - } - else if (self.selectedAnnotation) + // there is at least one nearby annotation; select one + // + // first, sort for comparison and iteration + std::sort(nearbyAnnotations.begin(), nearbyAnnotations.end()); + + if (nearbyAnnotations == self.annotationsNearbyLastTap) { - // otherwise increment the selection through the candidates - uint32_t currentID = [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] objectForKey:MGLAnnotationIDKey] unsignedIntValue]; - auto result = std::find(self.annotationsNearbyLastTap.begin(), self.annotationsNearbyLastTap.end(), currentID); - auto distance = std::distance(self.annotationsNearbyLastTap.begin(), result); - newSelectedAnnotationID = self.annotationsNearbyLastTap[distance + 1]; + // the selection candidates haven't changed; cycle through them + if (self.selectedAnnotation && + [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] + objectForKey:MGLAnnotationIDKey] unsignedIntValue] == self.annotationsNearbyLastTap.back()) + { + // the selected annotation is the last in the set; cycle back to the first + // note: this could be the selected annotation if only one in set + newSelectedAnnotationID = self.annotationsNearbyLastTap.front(); + } + else if (self.selectedAnnotation) + { + // otherwise increment the selection through the candidates + uint32_t currentID = [[[self.annotationIDsByAnnotation objectForKey:self.selectedAnnotation] objectForKey:MGLAnnotationIDKey] unsignedIntValue]; + auto result = std::find(self.annotationsNearbyLastTap.begin(), self.annotationsNearbyLastTap.end(), currentID); + auto distance = std::distance(self.annotationsNearbyLastTap.begin(), result); + newSelectedAnnotationID = self.annotationsNearbyLastTap[distance + 1]; + } + else + { + // no current selection; select the first one + newSelectedAnnotationID = self.annotationsNearbyLastTap.front(); + } } else { - // no current selection; select the first one + // start tracking a new set of nearby annotations + self.annotationsNearbyLastTap = nearbyAnnotations; + + // select the first one newSelectedAnnotationID = self.annotationsNearbyLastTap.front(); } } else { - // start tracking a new set of nearby annotations - self.annotationsNearbyLastTap = nearbyAnnotations; - - // select the first one - newSelectedAnnotationID = self.annotationsNearbyLastTap.front(); + // there are no nearby annotations; deselect if necessary + newSelectedAnnotationID = -1; } - } - else - { - // there are no nearby annotations; deselect if necessary - newSelectedAnnotationID = -1; - } - - if (newSelectedAnnotationID >= 0) - { - // find & select model object for selection - NSEnumerator *enumerator = self.annotationIDsByAnnotation.keyEnumerator; - while (id <MGLAnnotation> annotation = enumerator.nextObject) + if (newSelectedAnnotationID >= 0) { - if ([[[self.annotationIDsByAnnotation objectForKey:annotation] objectForKey:MGLAnnotationIDKey] integerValue] == newSelectedAnnotationID) + // find & select model object for selection + NSEnumerator *enumerator = self.annotationIDsByAnnotation.keyEnumerator; + + while (id <MGLAnnotation> annotation = enumerator.nextObject) { - // only change selection status if not the currently selected annotation - if ( ! [annotation isEqual:self.selectedAnnotation]) + if ([[[self.annotationIDsByAnnotation objectForKey:annotation] objectForKey:MGLAnnotationIDKey] integerValue] == newSelectedAnnotationID) { - [self selectAnnotation:annotation animated:YES]; - } + // only change selection status if not the currently selected annotation + if ( ! [annotation isEqual:self.selectedAnnotation]) + { + [self selectAnnotation:annotation animated:YES]; + } - // either way, we should stop enumerating - break; + // either way, we should stop enumerating + break; + } } } - } - else - { - // deselect any selected annotation - if (self.selectedAnnotation) [self deselectAnnotation:self.selectedAnnotation animated:YES]; + else + { + // deselect any selected annotation + if (self.selectedAnnotation) [self deselectAnnotation:self.selectedAnnotation animated:YES]; + } } } |