android.support.v4.view.accessibility.AccessibilityNodeInfoCompat#getChildCount ( )源码实例Demo

下面列出了android.support.v4.view.accessibility.AccessibilityNodeInfoCompat#getChildCount ( ) 实例代码,或者点击链接到github查看源代码,也可以在右侧发表评论。

源代码1 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
private static AccessibilityNodeInfoCompat refreshFromChild(
        AccessibilityNodeInfoCompat node) {
    if (node.getChildCount() > 0) {
        AccessibilityNodeInfoCompat firstChild = node.getChild(0);
        if (firstChild != null) {
            AccessibilityNodeInfoCompat parent = firstChild.getParent();
            firstChild.recycle();
            if (node.equals(parent)) {
                return parent;
            } else {
                recycleNodes(parent);
            }
        }
    }
    return null;
}
 
源代码2 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
private static AccessibilityNodeInfoCompat refreshFromParent(
        AccessibilityNodeInfoCompat node) {
    AccessibilityNodeInfoCompat parent = node.getParent();
    if (parent != null) {
        try {
            int childCount = parent.getChildCount();
            for (int i = 0; i < childCount; ++i) {
                AccessibilityNodeInfoCompat child = parent.getChild(i);
                if (node.equals(child)) {
                    return child;
                }
                recycleNodes(child);
            }
        } finally {
            parent.recycle();
        }
    }
    return null;
}
 
源代码3 项目: brailleback   文件: FocusFinder.java
public static AccessibilityNodeInfoCompat findFirstFocusableDescendant(
        AccessibilityNodeInfoCompat root, Context context) {
    // null guard and shortcut for leaf nodes.
    if (root == null || root.getChildCount() <= 0) {
        return null;
    }
    HashSet<AccessibilityNodeInfoCompat> seenNodes =
            new HashSet<AccessibilityNodeInfoCompat>();
    seenNodes.add(root);
    try {
        return findFirstFocusableDescendantInternal(
                root, context, seenNodes);
    } finally {
        seenNodes.remove(root);  // Not owned by us.
        AccessibilityNodeInfoUtils.recycleNodes(seenNodes);
    }
}
 
源代码4 项目: brailleback   文件: FocusFinder.java
public static AccessibilityNodeInfoCompat findLastFocusableDescendant(
        AccessibilityNodeInfoCompat root, Context context) {
    // null guard and shortcut for leaf nodes.
    if (root == null || root.getChildCount() <= 0) {
        return null;
    }
    HashSet<AccessibilityNodeInfoCompat> seenNodes =
            new HashSet<AccessibilityNodeInfoCompat>();
    seenNodes.add(root);
    try {
        return findLastFocusableDescendantInternal(
                root, context, seenNodes);
    } finally {
        seenNodes.remove(root);  // Not owned by us.
        AccessibilityNodeInfoUtils.recycleNodes(seenNodes);
    }
}
 
@Override
public void format(Editable result,
        Context context,
        AccessibilityNodeInfoCompat node) {
    boolean empty = (node.getChildCount() == 0);
    int res;
    if (AccessibilityNodeInfoUtils.nodeMatchesClassByType(context, node,
                    GridView.class)) {
        res = empty ? R.string.type_emptygridview : R.string.type_gridview;
    } else if (AccessibilityNodeInfoUtils.nodeMatchesClassByType(
        context, node, ScrollView.class)) {
        res = empty ? R.string.type_emptyscrollview
                : R.string.type_scrollview;
    } else {
        res = empty ? R.string.type_emptylistview : R.string.type_listview;
    }
    result.append(context.getString(res));
}
 
源代码6 项目: stetho   文件: AccessibilityUtil.java
/**
 * Returns whether the supplied {@link View} and {@link AccessibilityNodeInfoCompat} would
 * produce spoken feedback if it were accessibility focused.  NOTE: not all speaking nodes are
 * focusable.
 *
 * @param view The {@link View} to evaluate
 * @param node The {@link AccessibilityNodeInfoCompat} to evaluate
 * @return {@code true} if it meets the criterion for producing spoken feedback
 */
public static boolean isSpeakingNode(
    @Nullable AccessibilityNodeInfoCompat node,
    @Nullable View view) {
  if (node == null || view == null) {
    return false;
  }

  if (!node.isVisibleToUser()) {
    return false;
  }

  int important = ViewCompat.getImportantForAccessibility(view);
  if (important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS ||
      (important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO &&
          node.getChildCount() <= 0)) {
    return false;
  }

  return node.isCheckable() || hasText(node) || hasNonActionableSpeakingDescendants(node, view);
}
 
源代码7 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
/**
 * Returns the result of applying a filter using breadth-first traversal.
 *
 * @param context The parent context.
 * @param node The root node to traverse from.
 * @param filter The filter to satisfy.
 * @return The first node reached via BFS traversal that satisfies the
 *         filter.
 */
public static AccessibilityNodeInfoCompat searchFromBfs(
        Context context, AccessibilityNodeInfoCompat node, NodeFilter filter) {
    if (node == null) {
        return null;
    }

    final LinkedList<AccessibilityNodeInfoCompat> queue =
            new LinkedList<AccessibilityNodeInfoCompat>();

    queue.add(AccessibilityNodeInfoCompat.obtain(node));

    while (!queue.isEmpty()) {
        final AccessibilityNodeInfoCompat item = queue.removeFirst();

        if (filter.accept(context, item)) {
            return AccessibilityNodeInfoCompat.obtain(item);
        }

        final int childCount = item.getChildCount();

        for (int i = 0; i < childCount; i++) {
            final AccessibilityNodeInfoCompat child = item.getChild(i);

            if (child != null) {
                queue.addLast(child);
            }
        }
    }

    return null;
}
 
源代码8 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
/**
 * Returns the result of applying a filter using breadth-first traversal.
 *
 * @param context The parent context.
 * @param node The root node to traverse from.
 * @param filter The filter to satisfy.
 * @param maxResults The number of results to stop searching after
 * @return Returns all nodes reached via BFS traversal that satisfies the
 *         filter.
 */
public static List<AccessibilityNodeInfoCompat> searchAllFromBfs(Context context,
        AccessibilityNodeInfoCompat node, NodeFilter filter) {
    if (node == null) {
        return null;
    }

    final List<AccessibilityNodeInfoCompat> toReturn =
            new ArrayList<AccessibilityNodeInfoCompat>();
    final LinkedList<AccessibilityNodeInfoCompat> queue =
            new LinkedList<AccessibilityNodeInfoCompat>();

    queue.add(AccessibilityNodeInfoCompat.obtain(node));

    while (!queue.isEmpty()) {
        final AccessibilityNodeInfoCompat item = queue.removeFirst();

        if (filter.accept(context, item)) {
            toReturn.add(AccessibilityNodeInfoCompat.obtain(item));
        }

        final int childCount = item.getChildCount();

        for (int i = 0; i < childCount; i++) {
            final AccessibilityNodeInfoCompat child = item.getChild(i);

            if (child != null) {
                queue.addLast(child);
            }
        }
    }

    return toReturn;
}
 
源代码9 项目: brailleback   文件: AccessibilityNodeInfoRef.java
/**
 * Traverses to the next sibling of this node within its parent, returning
 * {@code true} on success.
 */
public boolean nextSibling() {
    if (mNode == null) {
        return false;
    }
    AccessibilityNodeInfoCompat parent = mNode.getParent();
    if (parent == null) {
        return false;
    }
    try {
        int childCount = parent.getChildCount();
        int childNumber = getChildNumber(parent);
        if (childNumber < 0) {
            return false;
        }
        for (int i = childNumber + 1; i < childCount; ++i) {
            AccessibilityNodeInfoCompat newNode =
                    parent.getChild(i);
            if (newNode == null) {
                return false;
            }
            if (AccessibilityNodeInfoUtils.isVisibleOrLegacy(newNode)) {
                reset(newNode);
                return true;
            }
            newNode.recycle();
        }
    } finally {
        parent.recycle();
    }
    return false;
}
 
源代码10 项目: brailleback   文件: AccessibilityNodeInfoRef.java
private int getChildNumber(AccessibilityNodeInfoCompat parent) {
    int ret = -1;
    int childCount = parent.getChildCount();
    for (int i = 0; i < childCount && ret < 0; ++i) {
        AccessibilityNodeInfoCompat child = parent.getChild(i);
        if (mNode.equals(child)) {
            ret = i;
        }
        if (child != null) {
            child.recycle();
        }
    }
    return ret;
}
 
源代码11 项目: brailleback   文件: WebInterfaceUtils.java
/**
 * Determines whether or not the given node contains native web content (and not ChromeVox).
 *
 * @param node The node to evaluate
 * @return {@code true} if the node contains native web content, {@code false} otherwise
 */
public static boolean hasNativeWebContent(AccessibilityNodeInfoCompat node) {
    if (node == null) {
        return false;
    }

    if (!supportsWebActions(node)) {
        return false;
    }

    // ChromeVox does not have sub elements, so if the parent element also has web content
    // this cannot be ChromeVox.
    AccessibilityNodeInfoCompat parent = node.getParent();
    if (supportsWebActions(parent)) {
        if (parent != null) {
            parent.recycle();
        }
        return true;
    }

    if (parent != null) {
        parent.recycle();
    }

    // ChromeVox never has child elements
    return node.getChildCount() > 0;
}
 
源代码12 项目: brailleback   文件: WebInterfaceUtils.java
/**
 * Determines whether or not the given node contains ChromeVox content.
 *
 * @param node The node to evaluate
 * @return {@code true} if the node contains ChromeVox content, {@code false} otherwise
 */
public static boolean hasLegacyWebContent(AccessibilityNodeInfoCompat node) {
    if (node == null) {
        return false;
    }

    if (!supportsWebActions(node)) {
        return false;
    }

    // ChromeVox does not have sub elements, so if the parent element also has web content
    // this cannot be ChromeVox.
    AccessibilityNodeInfoCompat parent = node.getParent();
    if (supportsWebActions(parent)) {
        if (parent != null) {
            parent.recycle();
        }

        return false;
    }

    if (parent != null) {
        parent.recycle();
    }

    // ChromeVox never has child elements
    return node.getChildCount() == 0;
}
 
源代码13 项目: brailleback   文件: NodeBrailler.java
/**
 * Formats {@code node} and its descendants, appending the result
 * to {@code sb}.
 */
private void formatSubtree(AccessibilityNodeInfoCompat node,
        Editable result) {
    if (!node.isVisibleToUser()) {
        return;
    }

    BrailleRule rule = mRuleRepository.find(node);
    SpannableStringBuilder subtreeResult = new SpannableStringBuilder();
    rule.format(subtreeResult, mContext, node);
    if (rule.includeChildren(node, mContext)) {
        int childCount = node.getChildCount();
        for (int i = 0; i < childCount; ++i) {
            AccessibilityNodeInfoCompat child = node.getChild(i);
            if (child == null) {
                continue;
            }
            formatSubtree(child, subtreeResult);
            child.recycle();
        }
    }
    if (!TextUtils.isEmpty(subtreeResult)) {
        // If the node is accessibility focused, add the focus span
        // here to cover the node and its formatted children.
        // This is a fallback in case the formatting rule hasn't set
        // focus by itself.
        if (node.isAccessibilityFocused()
                && subtreeResult.getSpans(0, subtreeResult.length(),
                        DisplaySpans.FocusSpan.class).length == 0) {
            DisplaySpans.addFocus(subtreeResult, 0,
                    subtreeResult.length());
        }
        addNodeSpanForUncovered(node, subtreeResult);
        StringUtils.appendWithSpaces(result, subtreeResult);
    }
}
 
源代码14 项目: brailleback   文件: FocusFinder.java
private static AccessibilityNodeInfoCompat
      findFirstFocusableDescendantInternal(
              AccessibilityNodeInfoCompat root, Context context,
              HashSet<AccessibilityNodeInfoCompat> seenNodes) {
    for (int i = 0, end = root.getChildCount(); i < end; ++i) {
        AccessibilityNodeInfoCompat child = root.getChild(i);
        if (child == null) {
            continue;
        }
        if (AccessibilityNodeInfoUtils.shouldFocusNode(
                        context, child)) {
            return child;
        }
        if (!seenNodes.add(child)) {
            LogUtils.log(FocusFinder.class, Log.ERROR,
                    "Cycle in node tree");
            child.recycle();
            return null;
        }
        AccessibilityNodeInfoCompat n =
                findFirstFocusableDescendantInternal(
                        child, context, seenNodes);
        if (n != null) {
            return n;
        }
    }
    return null;
}
 
源代码15 项目: brailleback   文件: FocusFinder.java
private static AccessibilityNodeInfoCompat
      findLastFocusableDescendantInternal(
              AccessibilityNodeInfoCompat root, Context context,
              HashSet<AccessibilityNodeInfoCompat> seenNodes) {
    for (int end = root.getChildCount(), i = end - 1; i >= 0; --i) {
        AccessibilityNodeInfoCompat child = root.getChild(i);
        if (child == null) {
            continue;
        }

        AccessibilityNodeInfoCompat n =
                findLastFocusableDescendantInternal(
                        child, context, seenNodes);
        if (n != null) {
            return n;
        }

        if (AccessibilityNodeInfoUtils.shouldFocusNode(context, child)) {
            return child;
        }
        if (!seenNodes.add(child)) {
            LogUtils.log(FocusFinder.class, Log.ERROR,
                    "Cycle in node tree");
            child.recycle();
            return null;
        }
    }
    return null;
}
 
源代码16 项目: timecat   文件: TimeCatMonitorService.java
private ArrayList<CopyNode> traverseNode(AccessibilityNodeInfoCompat nodeInfo, int width, int height) {
    ArrayList<CopyNode> nodeList = new ArrayList();
    if (nodeInfo != null && nodeInfo.getInfo() != null) {
        nodeInfo.refresh();

        for (int i = 0; i < nodeInfo.getChildCount(); ++i) {
            //递归遍历nodeInfo
            nodeList.addAll(traverseNode(nodeInfo.getChild(i), width, height));
        }

        if (nodeInfo.getClassName() != null && nodeInfo.getClassName().equals("android.webkit.WebView")) {
            return nodeList;
        } else {
            String content = null;
            String description = content;
            if (nodeInfo.getContentDescription() != null) {
                description = content;
                if (!"".equals(nodeInfo.getContentDescription())) {
                    description = nodeInfo.getContentDescription().toString();
                }
            }

            content = description;
            if (nodeInfo.getText() != null) {
                content = description;
                if (!"".equals(nodeInfo.getText())) {
                    content = nodeInfo.getText().toString();
                }
            }

            if (content != null) {
                Rect outBounds = new Rect();
                nodeInfo.getBoundsInScreen(outBounds);
                if (checkBound(outBounds, width, height)) {
                    nodeList.add(new CopyNode(outBounds, content));
                }
            }

            return nodeList;
        }
    } else {
        return nodeList;
    }
}
 
源代码17 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
/**
 * Returns whether a node should receive accessibility focus from
 * navigation. This method should never be called recursively, since it
 * traverses up the parent hierarchy on every call.
 *
 * @see #findFocusFromHover(Context, AccessibilityNodeInfoCompat)
 */
public static boolean shouldFocusNode(Context context, AccessibilityNodeInfoCompat node) {
    if (node == null) {
        return false;
    }

    if (!isVisibleOrLegacy(node)) {
        LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                "Don't focus, node is not visible");
        return false;
    }

    if (FILTER_ACCESSIBILITY_FOCUSABLE.accept(context, node)) {
        // TODO: This may still result in focusing non-speaking nodes, but it
        // won't prevent unlabeled buttons from receiving focus.
        if (node.getChildCount() <= 0) {
            LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                    "Focus, node is focusable and has no children");
            return true;
        } else if (isSpeakingNode(context, node)) {
            LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                    "Focus, node is focusable and has something to speak");
            return true;
        } else {
            LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                    "Don't focus, node is focusable but has nothing to speak");
            return false;
        }
    }

    // If this node has no focusable ancestors, but it still has text,
    // then it should receive focus from navigation and be read aloud.
    if (!hasMatchingAncestor(context, node, FILTER_ACCESSIBILITY_FOCUSABLE)
            && hasText(node)) {
        LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                "Focus, node has text and no focusable ancestors");
        return true;
    }

    LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
            "Don't focus, failed all focusability tests");
    return false;
}
 
源代码18 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
private static boolean hasNonActionableSpeakingChildren(
        Context context, AccessibilityNodeInfoCompat node) {
    final int childCount = node.getChildCount();

    AccessibilityNodeInfoCompat child = null;

    // Has non-actionable, speaking children?
    for (int i = 0; i < childCount; i++) {
        try {
            child = node.getChild(i);

            if (child == null) {
                LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                        "Child %d is null, skipping it", i);
                continue;
            }

            // Ignore invisible nodes.
            if (!isVisibleOrLegacy(child)) {
                LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                        "Child %d is invisible, skipping it", i);
                continue;
            }

            // Ignore focusable nodes.
            if (FILTER_ACCESSIBILITY_FOCUSABLE.accept(context, child)) {
                LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                        "Child %d is focusable, skipping it", i);
                continue;
            }

            // Recursively check non-focusable child nodes.
            // TODO: Mutual recursion is probably not a good idea.
            if (isSpeakingNode(context, child)) {
                LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
                        "Does have actionable speaking children (child %d)", i);
                return true;
            }
        } finally {
            AccessibilityNodeInfoUtils.recycleNodes(child);
        }
    }

    LogUtils.log(AccessibilityNodeInfoUtils.class, Log.VERBOSE,
            "Does not have non-actionable speaking children");
    return false;
}
 
源代码19 项目: stetho   文件: AccessibilityNodeInfoWrapper.java
@Nullable
public static String getFocusableReasons(View view) {
  AccessibilityNodeInfoCompat node = createNodeInfoFromView(view);
  try {
    boolean hasText = AccessibilityUtil.hasText(node);
    boolean isCheckable = node.isCheckable();
    boolean hasNonActionableSpeakingDescendants =
        AccessibilityUtil.hasNonActionableSpeakingDescendants(node, view);

    if (AccessibilityUtil.isActionableForAccessibility(node)) {
      if (node.getChildCount() <= 0) {
        return "View is actionable and has no children.";
      } else if (hasText) {
        return "View is actionable and has a description.";
      } else if (isCheckable) {
        return "View is actionable and checkable.";
      } else if (hasNonActionableSpeakingDescendants) {
        return "View is actionable and has non-actionable descendants with descriptions.";
      }
    }

    if (AccessibilityUtil.isTopLevelScrollItem(node, view)) {
      if (hasText) {
        return "View is a direct child of a scrollable container and has a description.";
      } else if (isCheckable) {
        return "View is a direct child of a scrollable container and is checkable.";
      } else if (hasNonActionableSpeakingDescendants) {
        return
            "View is a direct child of a scrollable container and has non-actionable " +
            "descendants with descriptions.";
      }
    }

    if (hasText) {
      return "View has a description and is not actionable, but has no actionable ancestor.";
    }

    return null;
  } finally {
    node.recycle();
  }
}
 
源代码20 项目: stetho   文件: AccessibilityNodeInfoWrapper.java
public static boolean getIgnored(View view) {
  int important = ViewCompat.getImportantForAccessibility(view);
  if (important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO ||
      important == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
    return true;
  }

  // Go all the way up the tree to make sure no parent has hidden its descendants
  ViewParent parent = view.getParent();
  while (parent instanceof View) {
    if (ViewCompat.getImportantForAccessibility((View) parent)
        == ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_NO_HIDE_DESCENDANTS) {
      return true;
    }
    parent = parent.getParent();
  }

  AccessibilityNodeInfoCompat node = createNodeInfoFromView(view);
  try {
    if (!node.isVisibleToUser()) {
      return true;
    }

    if (AccessibilityUtil.isAccessibilityFocusable(node, view)) {
      if (node.getChildCount() <= 0) {
        // Leaves that are accessibility focusable are never ignored, even if they don't have a
        // speakable description
        return false;
      } else if (AccessibilityUtil.isSpeakingNode(node, view)) {
        // Node is focusable and has something to speak
        return false;
      }

      // Node is focusable and has nothing to speak
      return true;
    }

    // If this node has no focusable ancestors, but it still has text,
    // then it should receive focus from navigation and be read aloud.
    if (!AccessibilityUtil.hasFocusableAncestor(node, view) && AccessibilityUtil.hasText(node)) {
      return false;
    }

    return true;
  } finally {
    node.recycle();
  }
}