summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorMinh Nguyễn <mxn@1ec5.org>2016-06-03 15:12:52 -0700
committerMinh Nguyễn <mxn@1ec5.org>2016-06-03 15:13:21 -0700
commit1f622fe48f06127fe9ee88b1b52b219debc69a7c (patch)
tree70093073bc0a3a1d04b454e37f5510a6c0d605ef /platform
parent1fdda914e0af473513982ba0a1c014dc2166eb14 (diff)
downloadqtlocation-mapboxgl-1f622fe48f06127fe9ee88b1b52b219debc69a7c.tar.gz
[ios] Made annotation views accessible
Annotation views now serve as their own accessibility elements. The developer’s own subclass of MGLAnnotationView can customize the view’s accessibility frame and/or path to more accurately reflect the visual hit target.
Diffstat (limited to 'platform')
-rw-r--r--platform/ios/src/MGLAnnotationContainerView.m14
-rw-r--r--platform/ios/src/MGLAnnotationView.mm43
-rw-r--r--platform/ios/src/MGLMapView.mm44
-rw-r--r--platform/ios/src/MGLMapView_Internal.h3
4 files changed, 85 insertions, 19 deletions
diff --git a/platform/ios/src/MGLAnnotationContainerView.m b/platform/ios/src/MGLAnnotationContainerView.m
index cd9c990ef0..9a823c839c 100644
--- a/platform/ios/src/MGLAnnotationContainerView.m
+++ b/platform/ios/src/MGLAnnotationContainerView.m
@@ -35,4 +35,18 @@
}
}
+#pragma mark UIAccessibility methods
+
+- (UIAccessibilityTraits)accessibilityTraits {
+ return UIAccessibilityTraitAdjustable;
+}
+
+- (void)accessibilityIncrement {
+ [self.superview.superview accessibilityIncrement];
+}
+
+- (void)accessibilityDecrement {
+ [self.superview.superview accessibilityDecrement];
+}
+
@end
diff --git a/platform/ios/src/MGLAnnotationView.mm b/platform/ios/src/MGLAnnotationView.mm
index 6f1d94c3e7..31657dbf4e 100644
--- a/platform/ios/src/MGLAnnotationView.mm
+++ b/platform/ios/src/MGLAnnotationView.mm
@@ -1,6 +1,8 @@
#import "MGLAnnotationView.h"
#import "MGLAnnotationView_Private.h"
-#import "MGLMapView.h"
+#import "MGLMapView_Internal.h"
+
+#import "NSBundle+MGLAdditions.h"
#include <mbgl/util/constants.hpp>
@@ -103,4 +105,43 @@
return [super actionForLayer:layer forKey:event];
}
+#pragma mark UIAccessibility methods
+
+- (BOOL)isAccessibilityElement {
+ return !self.hidden;
+}
+
+- (UIAccessibilityTraits)accessibilityTraits {
+ return UIAccessibilityTraitButton | UIAccessibilityTraitAdjustable;
+}
+
+- (NSString *)accessibilityLabel {
+ return [self.annotation respondsToSelector:@selector(title)] ? self.annotation.title : super.accessibilityLabel;
+}
+
+- (NSString *)accessibilityValue {
+ return [self.annotation respondsToSelector:@selector(subtitle)] ? self.annotation.subtitle : super.accessibilityValue;
+}
+
+- (NSString *)accessibilityHint {
+ return NSLocalizedStringWithDefaultValue(@"ANNOTATION_A11Y_HINT", nil, nil, @"Shows more info", @"Accessibility hint");
+}
+
+- (CGRect)accessibilityFrame {
+ CGRect accessibilityFrame = self.frame;
+ CGRect minimumFrame = CGRectInset({ self.center, CGSizeZero },
+ -MGLAnnotationAccessibilityElementMinimumSize.width / 2,
+ -MGLAnnotationAccessibilityElementMinimumSize.height / 2);
+ accessibilityFrame = CGRectUnion(accessibilityFrame, minimumFrame);
+ return accessibilityFrame;
+}
+
+- (void)accessibilityIncrement {
+ [self.superview accessibilityIncrement];
+}
+
+- (void)accessibilityDecrement {
+ [self.superview accessibilityDecrement];
+}
+
@end \ No newline at end of file
diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm
index ee4346f27b..1ad758dc77 100644
--- a/platform/ios/src/MGLMapView.mm
+++ b/platform/ios/src/MGLMapView.mm
@@ -98,7 +98,6 @@ const CGFloat MGLAnnotationImagePaddingForHitTest = 5;
/// Distance from the callout’s anchor point to the annotation it points to.
const CGFloat MGLAnnotationImagePaddingForCallout = 1;
-/// Minimum size of an annotation’s accessibility element.
const CGSize MGLAnnotationAccessibilityElementMinimumSize = CGSizeMake(10, 10);
/// Unique identifier representing a single annotation in mbgl.
@@ -2021,6 +2020,13 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
MGLAnnotationContext &annotationContext = _annotationContextsByAnnotationTag.at(annotationTag);
id <MGLAnnotation> annotation = annotationContext.annotation;
+ // Let the annotation view serve as its own accessibility element.
+ MGLAnnotationView *annotationView = annotationContext.annotationView;
+ if (annotationView && annotationView.superview)
+ {
+ return annotationView;
+ }
+
// Lazily create an accessibility element for the found annotation.
if ( ! annotationContext.accessibilityElement)
{
@@ -2028,17 +2034,8 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
}
// Update the accessibility element.
- MGLAnnotationView *annotationView = annotationContext.annotationView;
- CGRect annotationFrame;
- if (annotationView && annotationView.superview)
- {
- annotationFrame = [self convertRect:annotationView.bounds fromView:annotationView];
- }
- else
- {
- MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
- annotationFrame = [self frameOfImage:annotationImage.image centeredAtCoordinate:annotation.coordinate];
- }
+ MGLAnnotationImage *annotationImage = [self imageOfAnnotationWithTag:annotationTag];
+ CGRect annotationFrame = [self frameOfImage:annotationImage.image centeredAtCoordinate:annotation.coordinate];
CGPoint annotationFrameCenter = CGPointMake(CGRectGetMidX(annotationFrame), CGRectGetMidY(annotationFrame));
CGRect minimumFrame = CGRectInset({ annotationFrameCenter, CGSizeZero },
-MGLAnnotationAccessibilityElementMinimumSize.width / 2,
@@ -2075,17 +2072,28 @@ mbgl::Duration MGLDurationInSeconds(NSTimeInterval duration)
{
return 1;
}
- if ( ! [element isKindOfClass:[MGLAnnotationAccessibilityElement class]] &&
- element != self.attributionButton)
- {
- return NSNotFound;
- }
std::vector<MGLAnnotationTag> visibleAnnotations = [self annotationTagsInRect:self.bounds];
- if (element == self.attributionButton)
+
+ MGLAnnotationTag tag = MGLAnnotationTagNotFound;
+ if ([element isKindOfClass:[MGLAnnotationView class]])
+ {
+ id <MGLAnnotation> annotation = [(MGLAnnotationView *)element annotation];
+ tag = [self annotationTagForAnnotation:annotation];
+ }
+ else if ([element isKindOfClass:[MGLAnnotationAccessibilityElement class]])
+ {
+ tag = [(MGLAnnotationAccessibilityElement *)element tag];
+ }
+ else if (element == self.attributionButton)
{
return !!self.userLocationAnnotationView + visibleAnnotations.size();
}
+ else
+ {
+ return NSNotFound;
+ }
+
std::sort(visibleAnnotations.begin(), visibleAnnotations.end());
auto foundElement = std::find(visibleAnnotations.begin(), visibleAnnotations.end(),
((MGLAnnotationAccessibilityElement *)element).tag);
diff --git a/platform/ios/src/MGLMapView_Internal.h b/platform/ios/src/MGLMapView_Internal.h
index 0538dd0392..6225e11749 100644
--- a/platform/ios/src/MGLMapView_Internal.h
+++ b/platform/ios/src/MGLMapView_Internal.h
@@ -1,5 +1,8 @@
#import <Mapbox/Mapbox.h>
+/// Minimum size of an annotation’s accessibility element.
+extern const CGSize MGLAnnotationAccessibilityElementMinimumSize;
+
@interface MGLMapView (Internal)
/** Triggers another render pass even when it is not necessary. */