add talkback navigation support for links and header (#22447)

Summary:
1. add role description for heading
2. add talkback navigation support for link and header

Fixes #22440
Pull Request resolved: https://github.com/facebook/react-native/pull/22447

Differential Revision: D14205822

Pulled By: cpojer

fbshipit-source-id: 86bfc3bfc851f3544b1962012abaf8d1a357a9d2
This commit is contained in:
Wei Yang
2019-02-27 21:22:14 +01:00
committed by Mike Grabowski
parent 2b7346f4b3
commit 8e5eb6389f
3 changed files with 52 additions and 1 deletions
@@ -111,6 +111,31 @@ class AccessibilityAndroidExample extends React.Component {
</View>
</RNTesterBlock>
<RNTesterBlock title="Touchable with accessibilityRole = header">
<View
accessible={true}
accessibilityLabel="I'm a header, so I read it instead of embedded text."
accessibilityRole="header">
<Text style={{color: 'green'}}>This is</Text>
<Text style={{color: 'blue'}}>
nontouchable accessible view with label.
</Text>
</View>
</RNTesterBlock>
<RNTesterBlock title="Touchable with accessibilityRole = link">
<TouchableWithoutFeedback
onPress={() =>
ToastAndroid.show('Toasts work by default', ToastAndroid.SHORT)
}
accessibilityRole="link">
<View style={styles.embedded}>
<Text>Click me</Text>
<Text>Or not</Text>
</View>
</TouchableWithoutFeedback>
</RNTesterBlock>
<RNTesterBlock title="Touchable with accessibilityRole = button">
<TouchableWithoutFeedback
onPress={() =>
@@ -9,6 +9,9 @@ import android.content.Context;
import android.support.v4.view.AccessibilityDelegateCompat;
import android.support.v4.view.ViewCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat;
import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat.CollectionItemInfoCompat;
import android.text.SpannableString;
import android.text.style.URLSpan;
import android.view.View;
import com.facebook.react.R;
import java.util.Locale;
@@ -98,7 +101,6 @@ public class AccessibilityDelegateUtil {
public void onInitializeAccessibilityNodeInfo(
View host, AccessibilityNodeInfoCompat info) {
super.onInitializeAccessibilityNodeInfo(host, info);
setRole(info, accessibilityRole, view.getContext());
if (!(accessibilityHint == null)) {
String contentDescription=(String)info.getContentDescription();
if (contentDescription != null) {
@@ -108,6 +110,8 @@ public class AccessibilityDelegateUtil {
info.setContentDescription(accessibilityHint);
}
}
setRole(info, accessibilityRole, view.getContext());
}
});
}
@@ -127,6 +131,18 @@ public class AccessibilityDelegateUtil {
if (Locale.getDefault().getLanguage().equals(new Locale("en").getLanguage())) {
if (role.equals(AccessibilityRole.LINK)) {
nodeInfo.setRoleDescription(context.getString(R.string.link_description));
if (nodeInfo.getContentDescription() != null) {
SpannableString spannable = new SpannableString(nodeInfo.getContentDescription());
spannable.setSpan(new URLSpan(""), 0, spannable.length(), 0);
nodeInfo.setContentDescription(spannable);
}
if (nodeInfo.getText() != null) {
SpannableString spannable = new SpannableString(nodeInfo.getText());
spannable.setSpan(new URLSpan(""), 0, spannable.length(), 0);
nodeInfo.setText(spannable);
}
}
if (role.equals(AccessibilityRole.SEARCH)) {
nodeInfo.setRoleDescription(context.getString(R.string.search_description));
@@ -140,6 +156,12 @@ public class AccessibilityDelegateUtil {
if (role.equals(AccessibilityRole.ADJUSTABLE)) {
nodeInfo.setRoleDescription(context.getString(R.string.adjustable_description));
}
if (role.equals(AccessibilityRole.HEADER)) {
nodeInfo.setRoleDescription(context.getString(R.string.header_description));
final AccessibilityNodeInfoCompat.CollectionItemInfoCompat itemInfo =
AccessibilityNodeInfoCompat.CollectionItemInfoCompat.obtain(0, 1, 0, 1, true);
nodeInfo.setCollectionItemInfo(itemInfo);
}
}
if (role.equals(AccessibilityRole.IMAGEBUTTON)) {
nodeInfo.setClickable(true);
@@ -20,4 +20,8 @@
name="adjustable_description"
translatable="false"
>Adjustable</string>
<string
name="header_description"
translatable="false"
>Heading</string>
</resources>