mirror of
https://github.com/facebook/react-native.git
synced 2025-11-01 09:14:26 +00:00
Allow links that encorporate entire <Text> to be keyboard accessible
Summary:
I was helping a team with some keyboard link accessibility and they had this strange bug where a link was not keyboard accessible despite having `accessible={true}`. Something that fixed it for them was adding an `accessibilityLabel`, which makes no sense.
Turns out there is a bug when the link encompasses the entirety of the `Text` component. We have a special case for handling links of this manner, and right now we are not setting the `frame` property which is responsible for outlining the element when it takes focus.
This property is not one defined by UIKit, rather it is defined in RCTAccessibilityElement. We use it to derive the accessibilityFrame which has to be in screen coordinates. If you do not set the frame property then it is supposed to use the bounds of the container. This does not work properly, seemingly bc the name "frame" gets mangled internally in UIKit leading to UB. I changed the name the "something" and it works.
To remedy this lets just change the name
Changelog: [iOS] [Fixed]
Reviewed By: javache
Differential Revision: D72338838
fbshipit-source-id: da91d0c28baeb6765d4d604f3e47c91952167f9d
This commit is contained in:
committed by
Facebook GitHub Bot
parent
b0f2083d9d
commit
83fae860df
+1
-1
@@ -17,7 +17,7 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
*
|
||||
* Default value: `CGRectZero`.
|
||||
*/
|
||||
@property (nonatomic, assign) CGRect frame;
|
||||
@property (nonatomic, assign) CGRect frameInContainerSpace;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
||||
+2
-2
@@ -12,10 +12,10 @@
|
||||
- (CGRect)accessibilityFrame
|
||||
{
|
||||
UIView *container = (UIView *)self.accessibilityContainer;
|
||||
if (CGRectEqualToRect(_frame, CGRectZero)) {
|
||||
if (CGRectEqualToRect(_frameInContainerSpace, CGRectZero)) {
|
||||
return UIAccessibilityConvertFrameToScreenCoordinates(container.bounds, container);
|
||||
} else {
|
||||
return UIAccessibilityConvertFrameToScreenCoordinates(_frame, container);
|
||||
return UIAccessibilityConvertFrameToScreenCoordinates(_frameInContainerSpace, container);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+5
-5
@@ -62,20 +62,18 @@ using namespace facebook::react;
|
||||
accessibilityLabel = RCTNSStringFromString(_attributedString.getString());
|
||||
}
|
||||
// add first element has the text for the whole textview in order to read out the whole text
|
||||
RCTAccessibilityElement *firstElement =
|
||||
[[RCTAccessibilityElement alloc] initWithAccessibilityContainer:_view.superview];
|
||||
RCTAccessibilityElement *firstElement = [[RCTAccessibilityElement alloc] initWithAccessibilityContainer:_view];
|
||||
firstElement.isAccessibilityElement = YES;
|
||||
firstElement.accessibilityTraits = _view.accessibilityTraits;
|
||||
firstElement.accessibilityLabel = accessibilityLabel;
|
||||
firstElement.accessibilityLanguage = _view.accessibilityLanguage;
|
||||
firstElement.accessibilityFrame = UIAccessibilityConvertFrameToScreenCoordinates(_view.bounds, _view);
|
||||
[firstElement setAccessibilityActivationPoint:CGPointMake(
|
||||
firstElement.accessibilityFrame.origin.x + 1.0,
|
||||
firstElement.accessibilityFrame.origin.y + 1.0)];
|
||||
|
||||
[elements addObject:firstElement];
|
||||
|
||||
// add additional elements for those parts of text with embedded link so VoiceOver could specially recognize links
|
||||
|
||||
[_layoutManager getRectWithAttributedString:_attributedString
|
||||
paragraphAttributes:_paragraphAttributes
|
||||
enumerateAttribute:RCTTextAttributesAccessibilityRoleAttributeName
|
||||
@@ -84,6 +82,7 @@ using namespace facebook::react;
|
||||
if ((![value isEqualToString:@"button"] && ![value isEqualToString:@"link"])) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ([fragmentText isEqualToString:firstElement.accessibilityLabel]) {
|
||||
if ([value isEqualToString:@"link"]) {
|
||||
firstElement.accessibilityTraits |= UIAccessibilityTraitLink;
|
||||
@@ -93,6 +92,7 @@ using namespace facebook::react;
|
||||
// The fragment is the entire paragraph. This is handled as `firstElement`.
|
||||
return;
|
||||
}
|
||||
|
||||
if ([value isEqualToString:@"button"] &&
|
||||
([fragmentText isEqualToString:@"See Less"] ||
|
||||
[fragmentText isEqualToString:@"See More"])) {
|
||||
@@ -110,7 +110,7 @@ using namespace facebook::react;
|
||||
numberOfButtons++;
|
||||
}
|
||||
element.accessibilityLabel = fragmentText;
|
||||
element.frame = fragmentRect;
|
||||
element.frameInContainerSpace = fragmentRect;
|
||||
[elements addObject:element];
|
||||
}];
|
||||
|
||||
|
||||
Reference in New Issue
Block a user