in android/src/main/java/com/facebook/flipper/plugins/inspector/descriptors/utils/AccessibilityUtil.java [456:550]
public static CharSequence getTalkbackDescription(View view) {
final AccessibilityNodeInfoCompat node = ViewAccessibilityHelper.createNodeInfoFromView(view);
if (node == null) {
return null;
}
try {
final CharSequence contentDescription = node.getContentDescription();
final CharSequence nodeText = node.getText();
final boolean hasNodeText = !TextUtils.isEmpty(nodeText);
final boolean isEditText = view instanceof EditText;
StringBuilder talkbackSegments = new StringBuilder();
AccessibilityRoleUtil.AccessibilityRole role = AccessibilityRoleUtil.getRole(view);
String roleString = getRoleDescription(view);
boolean disabled =
AccessibilityEvaluationUtil.isActionableForAccessibility(node) && !node.isEnabled();
// EditText's prioritize their own text content over a contentDescription so skip this
if (!TextUtils.isEmpty(contentDescription) && (!isEditText || !hasNodeText)) {
// first prepend any status modifiers
addStateSegments(talkbackSegments, node, role);
// next add content description
talkbackSegments.append(contentDescription + delimiter);
// then role
if (roleString.length() > 0) {
talkbackSegments.append(roleString + delimiter);
}
// lastly disabled is appended if applicable
if (disabled) {
talkbackSegments.append("disabled" + delimiter);
}
return removeFinalDelimiter(talkbackSegments);
}
// EditText
if (hasNodeText) {
// skipped status checks above for EditText
// password
if (node.isPassword()) {
talkbackSegments.append("password" + delimiter);
}
// description
talkbackSegments.append(nodeText + delimiter);
// role
if (roleString.length() > 0) {
talkbackSegments.append(roleString + delimiter);
}
// disabled
if (disabled) {
talkbackSegments.append("disabled" + delimiter);
}
return removeFinalDelimiter(talkbackSegments);
}
// If there are child views and no contentDescription the text of all non-focusable children,
// comma separated, becomes the description.
if (view instanceof ViewGroup) {
final StringBuilder concatChildDescription = new StringBuilder();
final ViewGroup viewGroup = (ViewGroup) view;
for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
final View child = viewGroup.getChildAt(i);
final AccessibilityNodeInfoCompat childNodeInfo = AccessibilityNodeInfoCompat.obtain();
ViewCompat.onInitializeAccessibilityNodeInfo(child, childNodeInfo);
if (AccessibilityEvaluationUtil.isSpeakingNode(childNodeInfo, child)
&& !AccessibilityEvaluationUtil.isAccessibilityFocusable(childNodeInfo, child)) {
CharSequence childNodeDescription = getTalkbackDescription(child);
if (!TextUtils.isEmpty(childNodeDescription)) {
concatChildDescription.append(childNodeDescription + delimiter);
}
}
childNodeInfo.recycle();
}
return removeFinalDelimiter(concatChildDescription);
}
return null;
} finally {
node.recycle();
}
}