Skip to content

Commit e7e7116

Browse files
shamanskyhnguyenhuy
authored andcommitted
[#1451] Add support for UIAccessibilityCustomAction (#1452)
This PR adds support for UIAccessibilityCustomAction propagation through ASPendingState so that it can be picked up by VoiceOver.
1 parent 32f168d commit e7e7116

5 files changed

+59
-1
lines changed

Source/ASDisplayNode.h

+1
Original file line numberDiff line numberDiff line change
@@ -799,6 +799,7 @@ AS_EXTERN NSInteger const ASDefaultDrawingPriority;
799799
@property BOOL accessibilityViewIsModal;
800800
@property BOOL shouldGroupAccessibilityChildren;
801801
@property UIAccessibilityNavigationStyle accessibilityNavigationStyle;
802+
@property (nullable, copy) NSArray *accessibilityCustomActions API_AVAILABLE(ios(8.0),tvos(9.0));
802803
#if TARGET_OS_TV
803804
@property (nullable, copy) NSArray *accessibilityHeaderElements;
804805
#endif

Source/Private/ASDisplayNode+UIViewBridge.mm

+14
Original file line numberDiff line numberDiff line change
@@ -1256,6 +1256,20 @@ - (UIAccessibilityNavigationStyle)accessibilityNavigationStyle
12561256
return _getAccessibilityFromViewOrProperty(_accessibilityNavigationStyle, accessibilityNavigationStyle);
12571257
}
12581258

1259+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
1260+
- (void)setAccessibilityCustomActions:(NSArray *)accessibilityCustomActions
1261+
{
1262+
_bridge_prologue_write;
1263+
_setAccessibilityToViewAndProperty(_accessibilityCustomActions, accessibilityCustomActions, accessibilityCustomActions, accessibilityCustomActions);
1264+
}
1265+
1266+
- (NSArray *)accessibilityCustomActions
1267+
{
1268+
_bridge_prologue_read;
1269+
return _getAccessibilityFromViewOrProperty(_accessibilityCustomActions, accessibilityCustomActions);
1270+
}
1271+
#endif
1272+
12591273
#if TARGET_OS_TV
12601274
- (void)setAccessibilityHeaderElements:(NSArray *)accessibilityHeaderElements
12611275
{

Source/Private/ASDisplayNodeInternal.h

+1
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,7 @@ static constexpr CACornerMask kASCACornerAllCorners =
240240
BOOL _shouldGroupAccessibilityChildren;
241241
NSString *_accessibilityIdentifier;
242242
UIAccessibilityNavigationStyle _accessibilityNavigationStyle;
243+
NSArray *_accessibilityCustomActions;
243244
NSArray *_accessibilityHeaderElements;
244245
CGPoint _accessibilityActivationPoint;
245246
UIBezierPath *_accessibilityPath;

Source/Private/_ASPendingState.mm

+28-1
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@
7979
int setShouldGroupAccessibilityChildren:1;
8080
int setAccessibilityIdentifier:1;
8181
int setAccessibilityNavigationStyle:1;
82+
int setAccessibilityCustomActions:1;
8283
int setAccessibilityHeaderElements:1;
8384
int setAccessibilityActivationPoint:1;
8485
int setAccessibilityPath:1;
@@ -139,6 +140,7 @@ @implementation _ASPendingState
139140
BOOL shouldGroupAccessibilityChildren;
140141
NSString *accessibilityIdentifier;
141142
UIAccessibilityNavigationStyle accessibilityNavigationStyle;
143+
NSArray *accessibilityCustomActions;
142144
NSArray *accessibilityHeaderElements;
143145
CGPoint accessibilityActivationPoint;
144146
UIBezierPath *accessibilityPath;
@@ -285,6 +287,7 @@ - (instancetype)init
285287
shouldGroupAccessibilityChildren = NO;
286288
accessibilityIdentifier = nil;
287289
accessibilityNavigationStyle = UIAccessibilityNavigationStyleAutomatic;
290+
accessibilityCustomActions = nil;
288291
accessibilityHeaderElements = nil;
289292
accessibilityActivationPoint = CGPointZero;
290293
accessibilityPath = nil;
@@ -787,6 +790,19 @@ - (void)setAccessibilityNavigationStyle:(UIAccessibilityNavigationStyle)newAcces
787790
accessibilityNavigationStyle = newAccessibilityNavigationStyle;
788791
}
789792

793+
- (NSArray *)accessibilityCustomActions
794+
{
795+
return accessibilityCustomActions;
796+
}
797+
798+
- (void)setAccessibilityCustomActions:(NSArray *)newAccessibilityCustomActions
799+
{
800+
_flags.setAccessibilityCustomActions = YES;
801+
if (accessibilityCustomActions != newAccessibilityCustomActions) {
802+
accessibilityCustomActions = [newAccessibilityCustomActions copy];
803+
}
804+
}
805+
790806
#pragma clang diagnostic push
791807
#pragma clang diagnostic ignored "-Wdeprecated-implementations"
792808
- (NSArray *)accessibilityHeaderElements
@@ -1139,7 +1155,13 @@ - (void)applyToView:(UIView *)view withSpecialPropertiesHandling:(BOOL)specialPr
11391155

11401156
if (flags.setAccessibilityNavigationStyle)
11411157
view.accessibilityNavigationStyle = accessibilityNavigationStyle;
1142-
1158+
1159+
if (AS_AVAILABLE_IOS_TVOS(8, 9)) {
1160+
if (flags.setAccessibilityCustomActions) {
1161+
view.accessibilityCustomActions = accessibilityCustomActions;
1162+
}
1163+
}
1164+
11431165
#if TARGET_OS_TV
11441166
if (flags.setAccessibilityHeaderElements)
11451167
view.accessibilityHeaderElements = accessibilityHeaderElements;
@@ -1278,6 +1300,11 @@ + (_ASPendingState *)pendingViewStateFromView:(UIView *)view
12781300
pendingState.shouldGroupAccessibilityChildren = view.shouldGroupAccessibilityChildren;
12791301
pendingState.accessibilityIdentifier = view.accessibilityIdentifier;
12801302
pendingState.accessibilityNavigationStyle = view.accessibilityNavigationStyle;
1303+
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= __IPHONE_8_0
1304+
if (AS_AVAILABLE_IOS_TVOS(8, 9)) {
1305+
pendingState.accessibilityCustomActions = view.accessibilityCustomActions;
1306+
}
1307+
#endif
12811308
#if TARGET_OS_TV
12821309
pendingState.accessibilityHeaderElements = view.accessibilityHeaderElements;
12831310
#endif

Tests/ASDisplayNodeTests.mm

+15
Original file line numberDiff line numberDiff line change
@@ -498,6 +498,7 @@ - (void)checkValuesMatchDefaults:(ASDisplayNode *)node isLayerBacked:(BOOL)isLay
498498
XCTAssertEqual(NO, node.accessibilityElementsHidden, @"default accessibilityElementsHidden is broken %@", hasLoadedView);
499499
XCTAssertEqual(NO, node.accessibilityViewIsModal, @"default accessibilityViewIsModal is broken %@", hasLoadedView);
500500
XCTAssertEqual(NO, node.shouldGroupAccessibilityChildren, @"default shouldGroupAccessibilityChildren is broken %@", hasLoadedView);
501+
XCTAssertEqual((id)nil, node.accessibilityCustomActions, @"default acccessibilityCustomActions is broken %@", hasLoadedView);
501502

502503
if (!isLayerBacked) {
503504
XCTAssertEqual(YES, node.userInteractionEnabled, @"default userInteractionEnabled broken %@", hasLoadedView);
@@ -554,6 +555,12 @@ - (UIImage *)bogusImage
554555
return bogusImage;
555556
}
556557

558+
- (BOOL)dummySelector
559+
{
560+
// no-op; only used for testing of UIAccessibilityCustomAction propagation
561+
return YES;
562+
}
563+
557564
- (void)checkValuesMatchSetValues:(ASDisplayNode *)node isLayerBacked:(BOOL)isLayerBacked
558565
{
559566
NSString *targetName = isLayerBacked ? @"layer" : @"view";
@@ -608,6 +615,11 @@ - (void)checkValuesMatchSetValues:(ASDisplayNode *)node isLayerBacked:(BOOL)isLa
608615
XCTAssertEqual(YES, node.accessibilityViewIsModal, @"accessibilityViewIsModal broken %@", hasLoadedView);
609616
XCTAssertEqual(YES, node.shouldGroupAccessibilityChildren, @"shouldGroupAccessibilityChildren broken %@", hasLoadedView);
610617
XCTAssertEqual(UIAccessibilityNavigationStyleSeparate, node.accessibilityNavigationStyle, @"accessibilityNavigationStyle broken %@", hasLoadedView);
618+
if (AS_AVAILABLE_IOS_TVOS(8, 9)) {
619+
XCTAssertNotNil(node.accessibilityCustomActions, @"accessibilityCustomActions broken %@", hasLoadedView);
620+
XCTAssertEqualObjects(@"custom action", ((UIAccessibilityCustomAction *)(node.accessibilityCustomActions.firstObject)).name, @"accessibilityCustomActions broken %@", hasLoadedView);
621+
}
622+
611623
XCTAssertTrue(CGPointEqualToPoint(CGPointMake(1.0, 1.0), node.accessibilityActivationPoint), @"accessibilityActivationPoint broken %@", hasLoadedView);
612624
XCTAssertNotNil(node.accessibilityPath, @"accessibilityPath broken %@", hasLoadedView);
613625

@@ -679,6 +691,9 @@ - (void)checkSimpleBridgePropertiesSetPropagate:(BOOL)isLayerBacked
679691
node.accessibilityViewIsModal = YES;
680692
node.shouldGroupAccessibilityChildren = YES;
681693
node.accessibilityNavigationStyle = UIAccessibilityNavigationStyleSeparate;
694+
if (AS_AVAILABLE_IOS_TVOS(8, 9)) {
695+
node.accessibilityCustomActions = @[ [[UIAccessibilityCustomAction alloc] initWithName:@"custom action" target:self selector:@selector(dummySelector)] ];
696+
}
682697
node.accessibilityActivationPoint = CGPointMake(1.0, 1.0);
683698
node.accessibilityPath = [UIBezierPath bezierPath];
684699

0 commit comments

Comments
 (0)