下面列出了怎么用android.view.accessibility.AccessibilityNodeInfo.AccessibilityAction的API类实例代码及写法,或者点击链接到github查看源代码。
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
final int columnsCount = getNumColumns();
final int rowsCount = getCount() / columnsCount;
final int selectionMode = getSelectionModeForAccessibility();
final CollectionInfo collectionInfo = CollectionInfo.obtain(
rowsCount, columnsCount, false, selectionMode);
info.setCollectionInfo(collectionInfo);
if (columnsCount > 0 || rowsCount > 0) {
info.addAction(AccessibilityAction.ACTION_SCROLL_TO_POSITION);
}
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
node.setClassName(getClass().getName());
node.addAction(AccessibilityAction.ACTION_CLICK);
final int type = getTypeFromId(virtualViewId);
final int value = getValueFromId(virtualViewId);
final CharSequence description = getVirtualViewDescription(type, value);
node.setContentDescription(description);
getBoundsForVirtualView(virtualViewId, mTempRect);
node.setBoundsInParent(mTempRect);
final boolean selected = isVirtualViewSelected(type, value);
node.setSelected(selected);
final int nextId = getVirtualViewIdAfter(type, value);
if (nextId != INVALID_ID) {
node.setTraversalBefore(RadialTimePickerView.this, nextId);
}
}
@TargetApi(21)
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ACCESSIBILITY_CLASS_NAME);
info.setContentDescription(getProgressText());
if (duration <= 0) {
return;
}
if (Util.SDK_INT >= 21) {
info.addAction(AccessibilityAction.ACTION_SCROLL_FORWARD);
info.addAction(AccessibilityAction.ACTION_SCROLL_BACKWARD);
} else {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD);
}
}
public LauncherAccessibilityDelegate(Launcher launcher) {
mLauncher = launcher;
mActions.put(REMOVE, new AccessibilityAction(REMOVE,
launcher.getText(R.string.remove_drop_target_label)));
mActions.put(INFO, new AccessibilityAction(INFO,
launcher.getText(R.string.app_info_drop_target_label)));
mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
launcher.getText(R.string.uninstall_drop_target_label)));
mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
launcher.getText(R.string.action_add_to_workspace)));
mActions.put(MOVE, new AccessibilityAction(MOVE,
launcher.getText(R.string.action_move)));
mActions.put(MOVE_TO_WORKSPACE, new AccessibilityAction(MOVE_TO_WORKSPACE,
launcher.getText(R.string.action_move_to_workspace)));
mActions.put(RESIZE, new AccessibilityAction(RESIZE,
launcher.getText(R.string.action_resize)));
mActions.put(DEEP_SHORTCUTS, new AccessibilityAction(DEEP_SHORTCUTS,
launcher.getText(R.string.action_deep_shortcut)));
}
/**
* Returns {@code true} if the node supports at least one of the specified actions. To check
* whether a node supports multiple actions, combine them using the {@code |} (logical OR)
* operator.
*
* <p>Note: this method will check against the getActions() method of AccessibilityNodeInfo,
* which will not contain information for actions introduced in API level 21 or later.
*
* @param node The node to check.
* @param actions The actions to check.
* @return {@code true} if at least one action is supported.
*/
public static boolean supportsAnyAction(AccessibilityNodeInfoCompat node,
AccessibilityAction... actions) {
if (node != null) {
// Unwrap the node and compare AccessibilityActions because AccessibilityActions, unlike
// AccessibilityActionCompats, are static (so checks for equality work correctly).
final List<AccessibilityAction> supportedActions = node.unwrap().getActionList();
for (AccessibilityAction action : actions) {
if (supportedActions.contains(action)) {
return true;
}
}
}
return false;
}
public LauncherAccessibilityDelegate(Launcher launcher) {
mLauncher = launcher;
mActions.put(REMOVE, new AccessibilityAction(REMOVE,
launcher.getText(R.string.delete_target_label)));
mActions.put(INFO, new AccessibilityAction(INFO,
launcher.getText(R.string.info_target_label)));
mActions.put(UNINSTALL, new AccessibilityAction(UNINSTALL,
launcher.getText(R.string.delete_target_uninstall_label)));
mActions.put(ADD_TO_WORKSPACE, new AccessibilityAction(ADD_TO_WORKSPACE,
launcher.getText(R.string.action_add_to_workspace)));
mActions.put(MOVE, new AccessibilityAction(MOVE,
launcher.getText(R.string.action_move)));
mActions.put(MOVE_TO_WORKSPACE, new AccessibilityAction(MOVE_TO_WORKSPACE,
launcher.getText(R.string.action_move_to_workspace)));
mActions.put(RESIZE, new AccessibilityAction(RESIZE,
launcher.getText(R.string.action_resize)));
}
/**
* Returns {@code true} if the node supports at least one of the specified actions. This method
* supports actions introduced in API level 21 and later. However, it does not support bitmasks.
*
* @param node The node to check
* @param actions The actions to check
* @return {@code true} if at least one action is supported
*/
// TODO: Use A11yActionCompat once AccessibilityActionCompat#equals is overridden
public static boolean supportsAnyAction(
AccessibilityNodeInfoCompat node, AccessibilityAction... actions) {
if (node == null) {
return false;
}
// Unwrap the node and compare AccessibilityActions because AccessibilityActions, unlike
// AccessibilityActionCompats, are static (so checks for equality work correctly).
final List<AccessibilityAction> supportedActions = node.unwrap().getActionList();
for (AccessibilityAction action : actions) {
if (supportedActions.contains(action)) {
return true;
}
}
return false;
}
/**
* Returns the scroll action for the given {@link TraversalStrategy.SearchDirection} if the scroll
* action is available on the current SDK version. Otherwise, returns 0.
*/
public static int convertSearchDirectionToScrollAction(
@TraversalStrategy.SearchDirection int direction) {
if (direction == TraversalStrategy.SEARCH_FOCUS_FORWARD) {
return AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD;
} else if (direction == TraversalStrategy.SEARCH_FOCUS_BACKWARD) {
return AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD;
} else {
if (direction == TraversalStrategy.SEARCH_FOCUS_LEFT) {
return AccessibilityAction.ACTION_SCROLL_LEFT.getId();
} else if (direction == TraversalStrategy.SEARCH_FOCUS_RIGHT) {
return AccessibilityAction.ACTION_SCROLL_RIGHT.getId();
} else if (direction == TraversalStrategy.SEARCH_FOCUS_UP) {
return AccessibilityAction.ACTION_SCROLL_UP.getId();
} else if (direction == TraversalStrategy.SEARCH_FOCUS_DOWN) {
return AccessibilityAction.ACTION_SCROLL_DOWN.getId();
}
}
return 0;
}
/**
* Returns the {@link TraversalStrategy.SearchDirectionOrUnknown} for the given scroll action;
* {@link TraversalStrategy#SEARCH_FOCUS_UNKNOWN} is returned for a scroll action that can't be
* handled (e.g. because the current API level doesn't support it).
*/
public static @TraversalStrategy.SearchDirectionOrUnknown int
convertScrollActionToSearchDirection(int scrollAction) {
if (scrollAction == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD) {
return TraversalStrategy.SEARCH_FOCUS_FORWARD;
} else if (scrollAction == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD) {
return TraversalStrategy.SEARCH_FOCUS_BACKWARD;
} else {
if (scrollAction == AccessibilityAction.ACTION_SCROLL_LEFT.getId()) {
return TraversalStrategy.SEARCH_FOCUS_LEFT;
} else if (scrollAction == AccessibilityAction.ACTION_SCROLL_RIGHT.getId()) {
return TraversalStrategy.SEARCH_FOCUS_RIGHT;
} else if (scrollAction == AccessibilityAction.ACTION_SCROLL_UP.getId()) {
return TraversalStrategy.SEARCH_FOCUS_UP;
} else if (scrollAction == AccessibilityAction.ACTION_SCROLL_DOWN.getId()) {
return TraversalStrategy.SEARCH_FOCUS_DOWN;
}
}
return TraversalStrategy.SEARCH_FOCUS_UNKNOWN;
}
/** @hide */
@Override
public void onInitializeAccessibilityNodeInfoInternal(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfoInternal(info);
final int rowsCount = getCount();
final int selectionMode = getSelectionModeForAccessibility();
final CollectionInfo collectionInfo = CollectionInfo.obtain(
rowsCount, 1, false, selectionMode);
info.setCollectionInfo(collectionInfo);
if (rowsCount > 0) {
info.addAction(AccessibilityAction.ACTION_SCROLL_TO_POSITION);
}
}
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_FORWARD);
info.addAction(AccessibilityNodeInfo.AccessibilityAction.ACTION_SCROLL_BACKWARD);
}
@Override
protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfo node) {
final boolean hasBounds = getBoundsForDay(virtualViewId, mTempRect);
if (!hasBounds) {
// The day is invalid, kill the node.
mTempRect.setEmpty();
node.setContentDescription("");
node.setBoundsInParent(mTempRect);
node.setVisibleToUser(false);
return;
}
node.setText(getDayText(virtualViewId));
node.setContentDescription(getDayDescription(virtualViewId));
node.setBoundsInParent(mTempRect);
final boolean isDayEnabled = isDayEnabled(virtualViewId);
if (isDayEnabled) {
node.addAction(AccessibilityAction.ACTION_CLICK);
}
node.setEnabled(isDayEnabled);
if (virtualViewId == mActivatedDay) {
// TODO: This should use activated once that's supported.
node.setChecked(true);
}
}
public OverviewScreenAccessibilityDelegate(Workspace workspace) {
mWorkspace = workspace;
Context context = mWorkspace.getContext();
boolean isRtl = Utilities.isRtl(context.getResources());
mActions.put(MOVE_BACKWARD, new AccessibilityAction(MOVE_BACKWARD,
context.getText(isRtl ? R.string.action_move_screen_right :
R.string.action_move_screen_left)));
mActions.put(MOVE_FORWARD, new AccessibilityAction(MOVE_FORWARD,
context.getText(isRtl ? R.string.action_move_screen_left :
R.string.action_move_screen_right)));
}
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
Context context = host.getContext();
info.addAction(new AccessibilityAction(OVERVIEW, context.getText(OVERVIEW)));
if (Utilities.isWallpaperAllowed(context)) {
info.addAction(new AccessibilityAction(WALLPAPERS, context.getText(WALLPAPERS)));
}
info.addAction(new AccessibilityAction(WIDGETS, context.getText(WIDGETS)));
info.addAction(new AccessibilityAction(SETTINGS, context.getText(SETTINGS)));
}
private List<AccessibilityAction> getActionList() {
if (mIcon == null || !(mIcon.getTag() instanceof ItemInfo)) {
return Collections.EMPTY_LIST;
}
AccessibilityNodeInfo info = AccessibilityNodeInfo.obtain();
mDelegate.addSupportedActions(mIcon, info, true);
List<AccessibilityAction> result = new ArrayList<>(info.getActionList());
info.recycle();
return result;
}
public boolean show() {
List<AccessibilityAction> actions = getActionList();
if (actions.isEmpty()) {
return false;
}
PopupMenu popup = new PopupMenu(mLauncher, mIcon);
popup.setOnMenuItemClickListener(this);
Menu menu = popup.getMenu();
for (AccessibilityAction action : actions) {
menu.add(Menu.NONE, action.getId(), Menu.NONE, action.getLabel());
}
popup.show();
return true;
}
@Override
public void onInitializeAccessibilityNodeInfo(View host, AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(host, info);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
return;
}
CoordinatorLayout.LayoutParams layoutParams = (CoordinatorLayout.LayoutParams) card
.getLayoutParams();
int gravity = layoutParams.gravity;
boolean isOnLeft = (gravity & Gravity.LEFT) == Gravity.LEFT;
boolean isOnRight = (gravity & Gravity.RIGHT) == Gravity.RIGHT;
boolean isOnTop = (gravity & Gravity.TOP) == Gravity.TOP;
boolean isOnBottom = (gravity & Gravity.BOTTOM) == Gravity.BOTTOM;
boolean isOnCenter = (gravity & Gravity.HORIZONTAL_GRAVITY_MASK) == Gravity.CENTER_HORIZONTAL;
if (!(isOnTop && isOnLeft)) {
info.addAction(new AccessibilityAction(R.id.move_card_top_left_action,
getString(R.string.cat_card_action_move_top_left)));
}
if (!(isOnTop && isOnRight)) {
info.addAction(new AccessibilityAction(R.id.move_card_top_right_action,
getString(R.string.cat_card_action_move_top_right)));
}
if (!(isOnBottom && isOnLeft)) {
info.addAction(new AccessibilityAction(R.id.move_card_bottom_left_action,
getString(R.string.cat_card_action_move_bottom_left)));
}
if (!(isOnBottom && isOnRight)) {
info.addAction(new AccessibilityAction(
R.id.move_card_bottom_right_action,
getString(R.string.cat_card_action_move_bottom_right)));
}
if (!isOnCenter) {
info.addAction(new AccessibilityAction(
R.id.move_card_center_action,
getString(R.string.cat_card_action_move_center)));
}
}
public OverviewScreenAccessibilityDelegate(Workspace workspace) {
mWorkspace = workspace;
Context context = mWorkspace.getContext();
boolean isRtl = Utilities.isRtl(context.getResources());
mActions.put(MOVE_BACKWARD, new AccessibilityAction(MOVE_BACKWARD,
context.getText(isRtl ? R.string.action_move_screen_right :
R.string.action_move_screen_left)));
mActions.put(MOVE_FORWARD, new AccessibilityAction(MOVE_FORWARD,
context.getText(isRtl ? R.string.action_move_screen_left :
R.string.action_move_screen_right)));
}
/**
* Perform accessibility action ACTION_SET_PROGRESS on the node
*
* @param value desired progress value
* @return true if action performed successfully
*/
@TargetApi(Build.VERSION_CODES.N)
public static boolean setProgressValue(final AccessibilityNodeInfo node, final float value) {
if (!node.getActionList().contains(AccessibilityAction.ACTION_SET_PROGRESS)) {
Logger.debug("The element does not support ACTION_SET_PROGRESS action.");
return false;
}
Logger.debug(String.format(
"Trying to perform ACTION_SET_PROGRESS accessibility action with value %s", value));
final Bundle args = new Bundle();
args.putFloat(AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE, value);
return node.performAction(AccessibilityAction.ACTION_SET_PROGRESS.getId(), args);
}
@Override
public boolean accept(TalkBackService service, AccessibilityNodeInfoCompat node) {
if (!BuildVersionUtils.isAtLeastN()) {
return false;
}
return AccessibilityNodeInfoUtils.supportsAction(
node, AccessibilityNodeInfo.AccessibilityAction.ACTION_SET_PROGRESS.getId());
}
static void setProgress(AccessibilityNodeInfoCompat node, int progress) {
RangeInfoCompat rangeInfo = node.getRangeInfo();
if (rangeInfo != null && progress >= 0 && progress <= 100) {
Bundle args = new Bundle();
args.putFloat(
AccessibilityNodeInfo.ACTION_ARGUMENT_PROGRESS_VALUE,
percentToReal(progress, rangeInfo.getMin(), rangeInfo.getMax()));
EventId eventId = EVENT_ID_UNTRACKED; // Performance not tracked for menu events.
PerformActionUtils.performAction(
node, AccessibilityAction.ACTION_SET_PROGRESS.getId(), args, eventId);
}
}
public ClickActionDelegate(Context context, int resId) {
mClickAction = new AccessibilityAction(
AccessibilityNodeInfo.ACTION_CLICK, context.getString(resId));
}
public ShortcutMenuAccessibilityDelegate(Launcher launcher) {
super(launcher);
mActions.put(DISMISS_NOTIFICATION, new AccessibilityAction(DISMISS_NOTIFICATION,
launcher.getText(R.string.action_dismiss_notification)));
}
/** Creates a builder which can build ViewHierarchyActionAndroid from AccessibilityAction */
static Builder newBuilder(AccessibilityAction action) {
return new Builder(action);
}
Builder(AccessibilityAction action) {
this.actionId = action.getId();
this.actionLabel = action.getLabel();
}
public static boolean showOnScreen(
@Nullable AccessibilityNodeInfoCompat node, @Nullable EventId eventId) {
return performAction(node, AccessibilityAction.ACTION_SHOW_ON_SCREEN.getId(), eventId);
}
static void addAction(Object info, int id, CharSequence label) {
AccessibilityNodeInfo.AccessibilityAction aa =
new AccessibilityNodeInfo.AccessibilityAction(id, label);
((AccessibilityNodeInfo) info).addAction(aa);
}
static int getId(Object action) {
return ((AccessibilityNodeInfo.AccessibilityAction) action).getId();
}
static CharSequence getLabel(Object action) {
return ((AccessibilityNodeInfo.AccessibilityAction) action).getLabel();
}