Skip to content

Commit 1bbac5c

Browse files
authored
Merge pull request #37 from discord/dhleong/ellipsized-a11y-nodes-local-fork
Fix: a11y crash when an accessible link is ellipsized away
2 parents dcd8132 + 0589ad9 commit 1bbac5c

File tree

2 files changed

+35
-4
lines changed

2 files changed

+35
-4
lines changed

ReactAndroid/src/main/java/com/facebook/react/uimanager/ReactAccessibilityDelegate.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -571,9 +571,18 @@ protected void onPopulateNodeForVirtualView(
571571
return;
572572
}
573573

574+
// NOTE: The span may not actually have visible bounds within its parent,
575+
// due to line limits, etc.
576+
final Rect bounds = getBoundsInParent(accessibleTextSpan);
577+
if (bounds == null) {
578+
node.setContentDescription("");
579+
node.setBoundsInParent(new Rect(0, 0, 1, 1));
580+
return;
581+
}
582+
574583
node.setContentDescription(accessibleTextSpan.description);
575584
node.addAction(AccessibilityNodeInfoCompat.ACTION_CLICK);
576-
node.setBoundsInParent(getBoundsInParent(accessibleTextSpan));
585+
node.setBoundsInParent(bounds);
577586
node.setRoleDescription(mView.getResources().getString(R.string.link_description));
578587
node.setClassName(AccessibilityRole.getValue(AccessibilityRole.BUTTON));
579588
}
@@ -590,10 +599,19 @@ private Rect getBoundsInParent(AccessibilityLinks.AccessibleLink accessibleLink)
590599
return new Rect(0, 0, textView.getWidth(), textView.getHeight());
591600
}
592601

593-
Rect rootRect = new Rect();
594-
595602
double startOffset = accessibleLink.start;
596603
double endOffset = accessibleLink.end;
604+
605+
// Ensure the link hasn't been ellipsized away; in such cases,
606+
// getPrimaryHorizontal will crash (and the link isn't rendered anyway).
607+
int startOffsetLineNumber = textViewLayout.getLineForOffset((int) startOffset);
608+
int lineEndOffset = textViewLayout.getLineEnd(startOffsetLineNumber);
609+
if (startOffset > lineEndOffset) {
610+
return null;
611+
}
612+
613+
Rect rootRect = new Rect();
614+
597615
double startXCoordinates = textViewLayout.getPrimaryHorizontal((int) startOffset);
598616

599617
final Paint paint = new Paint();
@@ -603,7 +621,6 @@ private Rect getBoundsInParent(AccessibilityLinks.AccessibleLink accessibleLink)
603621
paint.setTextSize(textSize);
604622
int textWidth = (int) Math.ceil(paint.measureText(accessibleLink.description));
605623

606-
int startOffsetLineNumber = textViewLayout.getLineForOffset((int) startOffset);
607624
int endOffsetLineNumber = textViewLayout.getLineForOffset((int) endOffset);
608625
boolean isMultiline = startOffsetLineNumber != endOffsetLineNumber;
609626
textViewLayout.getLineBounds(startOffsetLineNumber, rootRect);

packages/rn-tester/js/examples/Accessibility/AccessibilityAndroidExample.android.js

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,20 @@ class AccessibilityAndroidExample extends React.Component<
6565
render(): React.Node {
6666
return (
6767
<RNTesterPage title={'Accessibility Android APIs'}>
68+
<RNTesterBlock title="Ellipsized Accessible Links">
69+
<Text numberOfLines={3}>
70+
<Text>
71+
Bacon {this.state.count} Ipsum{'\n'}
72+
</Text>
73+
<Text>Dolor sit amet{'\n'}</Text>
74+
<Text>Eggsecetur{'\n'}</Text>
75+
<Text>{'\n'}</Text>
76+
<Text accessibilityRole="link" onPress={this._addOne}>
77+
http://github.com
78+
</Text>
79+
</Text>
80+
</RNTesterBlock>
81+
6882
<RNTesterBlock title="LiveRegion">
6983
<TouchableWithoutFeedback onPress={this._addOne}>
7084
<View style={styles.embedded}>

0 commit comments

Comments
 (0)