diff options
author | Minh Nguyễn <mxn@1ec5.org> | 2017-09-09 15:13:52 -0700 |
---|---|---|
committer | Minh Nguyễn <mxn@1ec5.org> | 2017-11-02 15:19:53 -0700 |
commit | 0983893ca511a2bb157c41a7c173511c5a4a45f7 (patch) | |
tree | f9b2118d46bb979859695ac11bcc98e96a84c294 | |
parent | d9fe24176153f14d1c101f48993860ee776cbfb0 (diff) | |
download | qtlocation-mapboxgl-0983893ca511a2bb157c41a7c173511c5a4a45f7.tar.gz |
[ios] Summarize places, roads after zooming with VoiceOver
After zooming, MGLMapView’s accessibility value now indicates the number of visible roads and lists out a few places visible in the current viewport, starting with the features at the highest z-index (not necessarily the largest or the closest to the center of the view). Avoid saying that no annotations are visible.
-rw-r--r-- | platform/darwin/src/MGLStyle.mm | 27 | ||||
-rw-r--r-- | platform/darwin/src/MGLStyle_Private.h | 9 | ||||
-rw-r--r-- | platform/ios/resources/Base.lproj/Localizable.strings | 16 | ||||
-rw-r--r-- | platform/ios/resources/en.lproj/Localizable.stringsdict | 38 | ||||
-rw-r--r-- | platform/ios/src/MGLMapView.mm | 57 |
5 files changed, 127 insertions, 20 deletions
diff --git a/platform/darwin/src/MGLStyle.mm b/platform/darwin/src/MGLStyle.mm index 52efc7a85a..244fb94ef9 100644 --- a/platform/darwin/src/MGLStyle.mm +++ b/platform/darwin/src/MGLStyle.mm @@ -638,7 +638,7 @@ static NSURL *MGLStyleURL_trafficNight; self.URL ? [NSString stringWithFormat:@"\"%@\"", self.URL] : self.URL]; } -#pragma mark Style language preferences +#pragma mark Mapbox Streets source introspection - (void)setLocalizesLabels:(BOOL)localizesLabels { @@ -749,4 +749,29 @@ static NSURL *MGLStyleURL_trafficNight; } } +- (NS_SET_OF(MGLVectorSource *) *)mapboxStreetsSources { + return [self.sources objectsPassingTest:^BOOL (__kindof MGLVectorSource * _Nonnull source, BOOL * _Nonnull stop) { + return [source isKindOfClass:[MGLVectorSource class]] && source.mapboxStreets; + }]; +} + +- (NS_ARRAY_OF(MGLStyleLayer *) *)placeStyleLayers { + NSSet *streetsSourceIdentifiers = [self.mapboxStreetsSources valueForKey:@"identifier"]; + + NSSet *placeSourceLayerIdentifiers = [NSSet setWithObjects:@"marine_label", @"country_label", @"state_label", @"place_label", @"water_label", @"poi_label", @"rail_station_label", @"mountain_peak_label", nil]; + NSPredicate *isPlacePredicate = [NSPredicate predicateWithBlock:^BOOL (MGLVectorStyleLayer * _Nullable layer, NSDictionary<NSString *, id> * _Nullable bindings) { + return [layer isKindOfClass:[MGLVectorStyleLayer class]] && [streetsSourceIdentifiers containsObject:layer.sourceIdentifier] && [placeSourceLayerIdentifiers containsObject:layer.sourceLayerIdentifier]; + }]; + return [self.layers filteredArrayUsingPredicate:isPlacePredicate]; +} + +- (NS_ARRAY_OF(MGLStyleLayer *) *)roadStyleLayers { + NSSet *streetsSourceIdentifiers = [self.mapboxStreetsSources valueForKey:@"identifier"]; + + NSPredicate *isPlacePredicate = [NSPredicate predicateWithBlock:^BOOL (MGLVectorStyleLayer * _Nullable layer, NSDictionary<NSString *, id> * _Nullable bindings) { + return [layer isKindOfClass:[MGLVectorStyleLayer class]] && [streetsSourceIdentifiers containsObject:layer.sourceIdentifier] && [layer.sourceLayerIdentifier isEqualToString:@"road_label"]; + }]; + return [self.layers filteredArrayUsingPredicate:isPlacePredicate]; +} + @end diff --git a/platform/darwin/src/MGLStyle_Private.h b/platform/darwin/src/MGLStyle_Private.h index 92b08e844b..e5bd79dc02 100644 --- a/platform/darwin/src/MGLStyle_Private.h +++ b/platform/darwin/src/MGLStyle_Private.h @@ -14,6 +14,8 @@ namespace mbgl { @class MGLAttributionInfo; @class MGLMapView; @class MGLOpenGLStyleLayer; +@class MGLVectorSource; +@class MGLVectorStyleLayer; @interface MGLStyle (Private) @@ -30,4 +32,11 @@ namespace mbgl { @end +@interface MGLStyle (MGLStreetsAdditions) + +@property (nonatomic, readonly, copy) NS_ARRAY_OF(MGLVectorStyleLayer *) *placeStyleLayers; +@property (nonatomic, readonly, copy) NS_ARRAY_OF(MGLVectorStyleLayer *) *roadStyleLayers; + +@end + NS_ASSUME_NONNULL_END diff --git a/platform/ios/resources/Base.lproj/Localizable.strings b/platform/ios/resources/Base.lproj/Localizable.strings index 3f59262d71..815f7a3498 100644 --- a/platform/ios/resources/Base.lproj/Localizable.strings +++ b/platform/ios/resources/Base.lproj/Localizable.strings @@ -34,6 +34,9 @@ /* Accessibility label */ "INFO_A11Y_LABEL" = "About this map"; +/* List separator */ +"LIST_SEPARATOR" = ", "; + /* User-friendly error description */ "LOAD_MAP_FAILED_DESC" = "The map failed to load because an unknown error occurred."; @@ -46,8 +49,17 @@ /* Accessibility label */ "MAP_A11Y_LABEL" = "Map"; -/* Map accessibility value */ -"MAP_A11Y_VALUE" = "Zoom %1$dx\n%2$ld annotation(s) visible"; +/* Map accessibility value; {number of visible annotations} */ +"MAP_A11Y_VALUE_ANNOTATIONS" = "%ld annotation(s) visible."; + +/* Map accessibility value; {list of visible places} */ +"MAP_A11Y_VALUE_PLACES" = "Places visible: %@."; + +/* Map accessibility value; {number of visible roads} */ +"MAP_A11Y_VALUE_ROADS" = "%ld road(s) visible."; + +/* Map accessibility value; {zoom level} */ +"MAP_A11Y_VALUE_ZOOM" = "Zoom %dx."; /* User-friendly error description */ "PARSE_STYLE_FAILED_DESC" = "The map failed to load because the style is corrupted."; diff --git a/platform/ios/resources/en.lproj/Localizable.stringsdict b/platform/ios/resources/en.lproj/Localizable.stringsdict index e849318fe5..435b7bdfe8 100644 --- a/platform/ios/resources/en.lproj/Localizable.stringsdict +++ b/platform/ios/resources/en.lproj/Localizable.stringsdict @@ -2,22 +2,26 @@ <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <dict> - <key>MAP_A11Y_VALUE</key> + <key>MAP_A11Y_VALUE_ANNOTATIONS</key> <dict> <key>NSStringLocalizedFormatKey</key> - <string>%#@level@ -%#@count@</string> - <key>level</key> + <string>%#@count@</string> + <key>count</key> <dict> <key>NSStringFormatSpecTypeKey</key> <string>NSStringPluralRuleType</string> <key>NSStringFormatValueTypeKey</key> - <string>d</string> + <string>ld</string> <key>one</key> - <string>Zoom %dx</string> + <string>%d annotation visible</string> <key>other</key> - <string>Zoom %dx</string> + <string>%d annotations visible</string> </dict> + </dict> + <key>MAP_A11Y_VALUE_ROADS</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@count@</string> <key>count</key> <dict> <key>NSStringFormatSpecTypeKey</key> @@ -25,9 +29,25 @@ <key>NSStringFormatValueTypeKey</key> <string>ld</string> <key>one</key> - <string>%d annotation visible</string> + <string>%d road visible</string> <key>other</key> - <string>%d annotations visible</string> + <string>%d roads visible</string> + </dict> + </dict> + <key>MAP_A11Y_VALUE_ZOOM</key> + <dict> + <key>NSStringLocalizedFormatKey</key> + <string>%#@level@</string> + <key>level</key> + <dict> + <key>NSStringFormatSpecTypeKey</key> + <string>NSStringPluralRuleType</string> + <key>NSStringFormatValueTypeKey</key> + <string>d</string> + <key>one</key> + <string>Zoom %dx</string> + <key>other</key> + <string>Zoom %dx</string> </dict> </dict> </dict> diff --git a/platform/ios/src/MGLMapView.mm b/platform/ios/src/MGLMapView.mm index ed51754b0a..630688f05a 100644 --- a/platform/ios/src/MGLMapView.mm +++ b/platform/ios/src/MGLMapView.mm @@ -43,6 +43,7 @@ #import "MGLFoundation_Private.h" #import "MGLRendererFrontend.h" +#import "MGLVectorSource+MGLAdditions.h" #import "NSBundle+MGLAdditions.h" #import "NSDate+MGLAdditions.h" #import "NSException+MGLAdditions.h" @@ -2355,8 +2356,53 @@ public: - (NSString *)accessibilityValue { + NSMutableArray *facts = [NSMutableArray array]; + double zoomLevel = round(self.zoomLevel + 1); - return [NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"MAP_A11Y_VALUE", nil, nil, @"Zoom %dx\n%ld annotation(s) visible", @"Map accessibility value"), (int)zoomLevel, (long)self.accessibilityAnnotationCount]; + [facts addObject:[NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"MAP_A11Y_VALUE_ZOOM", nil, nil, @"Zoom %dx.", @"Map accessibility value; {zoom level}"), (int)zoomLevel]]; + + NSInteger annotationCount = self.accessibilityAnnotationCount; + if (annotationCount) { + [facts addObject:[NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"MAP_A11Y_VALUE_ANNOTATIONS", nil, nil, @"%ld annotation(s) visible.", @"Map accessibility value; {number of visible annotations}"), (long)self.accessibilityAnnotationCount]]; + } + + NSArray *placeFeatures = self.visiblePlaceFeatures; + if (placeFeatures.count) { + NSMutableArray *placesArray = [NSMutableArray arrayWithCapacity:placeFeatures.count]; + NSMutableSet *placesSet = [NSMutableSet setWithCapacity:placeFeatures.count]; + for (id <MGLFeature> placeFeature in placeFeatures.reverseObjectEnumerator) { + NSString *name = [placeFeature attributeForKey:@"name"]; + if (![placesSet containsObject:name]) { + [placesArray addObject:name]; + [placesSet addObject:name]; + } + if (placesArray.count >= 3) { + break; + } + } + NSString *placesString = [placesArray componentsJoinedByString:NSLocalizedStringWithDefaultValue(@"LIST_SEPARATOR", nil, nil, @", ", @"List separator")]; + [facts addObject:[NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"MAP_A11Y_VALUE_PLACES", nil, nil, @"Places visible: %@.", @"Map accessibility value; {list of visible places}"), placesString]]; + } + + NSArray *roadFeatures = self.visibleRoadFeatures; + if (roadFeatures.count) { + [facts addObject:[NSString stringWithFormat:NSLocalizedStringWithDefaultValue(@"MAP_A11Y_VALUE_ROADS", nil, nil, @"%ld road(s) visible.", @"Map accessibility value; {number of visible roads}"), roadFeatures.count]]; + } + + NSString *value = [facts componentsJoinedByString:@" "]; + return value; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visiblePlaceFeatures +{ + NSArray *placeStyleLayerIdentifiers = [self.style.placeStyleLayers valueForKey:@"identifier"]; + return [self visibleFeaturesInRect:self.bounds inStyleLayersWithIdentifiers:[NSSet setWithArray:placeStyleLayerIdentifiers]]; +} + +- (NS_ARRAY_OF(id <MGLFeature>) *)visibleRoadFeatures +{ + NSArray *roadStyleLayerIdentifiers = [self.style.roadStyleLayers valueForKey:@"identifier"]; + return [self visibleFeaturesInRect:self.bounds inStyleLayersWithIdentifiers:[NSSet setWithArray:roadStyleLayerIdentifiers]]; } - (CGRect)accessibilityFrame @@ -2390,14 +2436,9 @@ public: { if (self.calloutViewForSelectedAnnotation) { - return 2 /* selectedAnnotationCalloutView, mapViewProxyAccessibilityElement */; - } - NSInteger count = self.accessibilityAnnotationCount + 2 /* compass, attributionButton */; - if (self.userLocationAnnotationView) - { - count++; + return 2 /* calloutViewForSelectedAnnotation, mapViewProxyAccessibilityElement */; } - return count; + return !!self.userLocationAnnotationView + self.accessibilityAnnotationCount + self.visiblePlaceFeatures.count + 2 /* compass, attributionButton */; } - (NSInteger)accessibilityAnnotationCount |