Add accessibility role and role description to flipper
Summary:
This adds the concept of a custom role description to Flipper's accessibility inspector. This functionality was added in support library version 24.1, and supported in Litho as of D8066609.
This will show both the AccessibilityNodeInfo's raw roleDescription under the AccessibilityNodeInfo section, as well as the derived role description under the main Accessibility section (see highlighted elements in screenshot below).
The difference between the raw role description and the derived role description is that the derived description will show any default description a role is given, such as "Button" for button roles. This makes it clear that the role-description property will override those default strings.
Unfortunately making these mutable requires the AccessibilityRoleUtil class be restructured a bit to support EnumMapping for its roles, which isn't very straightforward due to these default descriptions being stored in the AccessibilityRole enum, so that will have to wait for a future diff.
Screenshot:
{F149099209}
Reviewed By: danielbuechele
Differential Revision: D13759563
fbshipit-source-id: 6eeb22a35f529663725630936af9967ea1f19c0c
This commit is contained in:
committed by
Facebook Github Bot
parent
aa365b990b
commit
fc1d32a3f9
@@ -1,11 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.flipper.plugins.inspector.descriptors;
|
||||
|
||||
import static com.facebook.flipper.plugins.inspector.InspectorValue.Type.Color;
|
||||
@@ -95,11 +93,15 @@ public class ViewDescriptor extends NodeDescriptor<View> {
|
||||
CharSequence name = nodeInfo.getClassName();
|
||||
nodeInfo.recycle();
|
||||
|
||||
if (name != null) {
|
||||
if (name != null && name != "") {
|
||||
return name.toString();
|
||||
}
|
||||
}
|
||||
return "NULL NODEINFO OR CLASSNAME";
|
||||
|
||||
// A node may have no name if a custom role description was set, but no
|
||||
// role, or if the AccessibilityNodeInfo could not be generated. If this is
|
||||
// the case name just give this node a generic name.
|
||||
return "AccessibilityNode";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE file in the root
|
||||
* directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.flipper.plugins.inspector.descriptors.utils;
|
||||
|
||||
import android.support.v4.view.ViewCompat;
|
||||
@@ -29,9 +27,9 @@ public class AccessibilityRoleUtil {
|
||||
* <p>The roles spoken by Talkback (roleStrings) should also be kept up to date and are found
|
||||
* here:
|
||||
*
|
||||
* <p>https://github.com/google/talkback/compositor/src/main/res/values/strings.xml
|
||||
* <p>https://github.com/google/talkback/blob/master/compositor/src/main/res/values/strings.xml
|
||||
*
|
||||
* <p>https://github.com/google/talkback/compositor/src/main/res/raw/compositor.json
|
||||
* <p>https://github.com/google/talkback/blob/master/compositor/src/main/res/raw/compositor.json
|
||||
*/
|
||||
public enum AccessibilityRole {
|
||||
NONE(null, ""),
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
/*
|
||||
* Copyright (c) 2018-present, Facebook, Inc.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
/**
|
||||
* Copyright (c) Facebook, Inc. and its affiliates.
|
||||
*
|
||||
* This source code is licensed under the MIT license found in the LICENSE
|
||||
* file in the root directory of this source tree.
|
||||
*/
|
||||
|
||||
package com.facebook.flipper.plugins.inspector.descriptors.utils;
|
||||
|
||||
import static android.content.Context.ACCESSIBILITY_SERVICE;
|
||||
@@ -468,10 +466,7 @@ public final class AccessibilityUtil {
|
||||
|
||||
StringBuilder talkbackSegments = new StringBuilder();
|
||||
AccessibilityRoleUtil.AccessibilityRole role = AccessibilityRoleUtil.getRole(view);
|
||||
String roleString = (String) node.getRoleDescription();
|
||||
if (roleString == null) {
|
||||
roleString = role.getRoleString();
|
||||
}
|
||||
String roleString = getRoleDescription(view);
|
||||
boolean disabled =
|
||||
AccessibilityEvaluationUtil.isActionableForAccessibility(node) && !node.isEnabled();
|
||||
|
||||
@@ -581,6 +576,7 @@ public final class AccessibilityUtil {
|
||||
.put("accessibility-focused", nodeInfo.isAccessibilityFocused())
|
||||
.put("checkable", nodeInfo.isCheckable())
|
||||
.put("checked", nodeInfo.isChecked())
|
||||
.put("class-name", nodeInfo.getClassName())
|
||||
.put("clickable", nodeInfo.isClickable())
|
||||
.put("content-description", nodeInfo.getContentDescription())
|
||||
.put("content-invalid", nodeInfo.isContentInvalid())
|
||||
@@ -598,7 +594,8 @@ public final class AccessibilityUtil {
|
||||
.put("scrollable", nodeInfo.isScrollable())
|
||||
.put("selected", nodeInfo.isSelected())
|
||||
.put("text", nodeInfo.getText())
|
||||
.put("visible-to-user", nodeInfo.isVisibleToUser());
|
||||
.put("visible-to-user", nodeInfo.isVisibleToUser())
|
||||
.put("role-description", getRoleDescription(nodeInfo));
|
||||
|
||||
nodeInfo.getBoundsInParent(bounds);
|
||||
nodeInfoProps.put(
|
||||
@@ -667,6 +664,8 @@ public final class AccessibilityUtil {
|
||||
CharSequence contentDescription =
|
||||
view.getContentDescription() != null ? view.getContentDescription() : "";
|
||||
props
|
||||
.put("role", AccessibilityRoleUtil.getRole(view).toString())
|
||||
.put("role-description", InspectorValue.mutable(getRoleDescription(view)))
|
||||
.put("content-description", InspectorValue.mutable(contentDescription))
|
||||
.put("focusable", InspectorValue.mutable(view.isFocusable()))
|
||||
.put("selected", InspectorValue.mutable(view.isSelected()))
|
||||
@@ -708,4 +707,34 @@ public final class AccessibilityUtil {
|
||||
.build();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getRoleDescription(View view) {
|
||||
AccessibilityNodeInfoCompat nodeInfo = ViewAccessibilityHelper.createNodeInfoFromView(view);
|
||||
String roleDescription = getRoleDescription(nodeInfo);
|
||||
nodeInfo.recycle();
|
||||
|
||||
if (roleDescription == null || roleDescription == "") {
|
||||
AccessibilityRoleUtil.AccessibilityRole role = AccessibilityRoleUtil.getRole(view);
|
||||
roleDescription = role.getRoleString();
|
||||
}
|
||||
|
||||
return roleDescription;
|
||||
}
|
||||
|
||||
public static @Nullable String getRoleDescription(AccessibilityNodeInfoCompat nodeInfo) {
|
||||
if (nodeInfo == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Custom role descriptions are only supported in support library version
|
||||
// 24.1 and higher, but there is no way to get support library version
|
||||
// info at runtime.
|
||||
try {
|
||||
return (String) nodeInfo.getRoleDescription();
|
||||
} catch (NullPointerException e) {
|
||||
// no-op
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user