diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2016-06-03 15:12:52 -0700 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2016-06-03 15:13:21 -0700 |
commit | 1f622fe48f06127fe9ee88b1b52b219debc69a7c (patch) | |
tree | 70093073bc0a3a1d04b454e37f5510a6c0d605ef /platform | |
parent | 1fdda914e0af473513982ba0a1c014dc2166eb14 (diff) | |
download | qtlocation-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.m | 14 | ||||
-rw-r--r-- | platform/ios/src/MGLAnnotationView.mm | 43 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 44 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView_Internal.h | 3 |
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. */ |