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

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

源代码1 项目: brailleback   文件: AccessibilityNodeInfoUtils.java
/**
 * Gets the text of a <code>node</code> by returning the content description
 * (if available) or by returning the text.
 *
 * @param node The node.
 * @return The node text.
 */
public static CharSequence getNodeText(AccessibilityNodeInfoCompat node) {
    if (node == null) {
        return null;
    }

    // Prefer content description over text.
    // TODO: Why are we checking the trimmed length?
    final CharSequence contentDescription = node.getContentDescription();
    if (!TextUtils.isEmpty(contentDescription)
            && (TextUtils.getTrimmedLength(contentDescription) > 0)) {
        return contentDescription;
    }

    final CharSequence text = node.getText();
    if (!TextUtils.isEmpty(text)
            && (TextUtils.getTrimmedLength(text) > 0)) {
        return text;
    }

    return null;
}
 
源代码2 项目: brailleback   文件: AutomationUtils.java
/**
 * Returns whether a node matches the class specified by
 * {@code className} and exactly match the text or content description
 * specified by {@code text}.
 */
private static boolean nodeMatchesFilter(Context context, AccessibilityNodeInfoCompat node,
        CharSequence referenceClassName, String findText) {
    final ClassLoadingManager loader = ClassLoadingManager.getInstance();
    final CharSequence nodeClass = node.getClassName();
    final CharSequence nodePackage = node.getPackageName();

    if (!loader.checkInstanceOf(context, nodeClass, nodePackage, referenceClassName)) {
        return false;
    }

    final CharSequence nodeText = node.getText();
    if (TextUtils.equals(findText, nodeText)) {
        return true;
    }

    final CharSequence nodeDesc = node.getContentDescription();
    if (TextUtils.equals(findText, nodeDesc)) {
        return true;
    }

    return false;
}
 
源代码3 项目: 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;
    }
}
 
源代码4 项目: letv   文件: ExploreByTouchHelper.java
private AccessibilityNodeInfoCompat createNodeForChild(int virtualViewId) {
    AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();
    node.setEnabled(true);
    node.setClassName(DEFAULT_CLASS_NAME);
    onPopulateNodeForVirtualView(virtualViewId, node);
    if (node.getText() == null && node.getContentDescription() == null) {
        throw new RuntimeException("Callbacks must add text or a content description in populateNodeForVirtualViewId()");
    }
    node.getBoundsInParent(this.mTempParentRect);
    if (this.mTempParentRect.isEmpty()) {
        throw new RuntimeException("Callbacks must set parent bounds in populateNodeForVirtualViewId()");
    }
    int actions = node.getActions();
    if ((actions & 64) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in populateNodeForVirtualViewId()");
    } else if ((actions & 128) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in populateNodeForVirtualViewId()");
    } else {
        node.setPackageName(this.mView.getContext().getPackageName());
        node.setSource(this.mView, virtualViewId);
        node.setParent(this.mView);
        if (this.mFocusedVirtualViewId == virtualViewId) {
            node.setAccessibilityFocused(true);
            node.addAction(128);
        } else {
            node.setAccessibilityFocused(false);
            node.addAction(64);
        }
        if (intersectVisibleToUser(this.mTempParentRect)) {
            node.setVisibleToUser(true);
            node.setBoundsInParent(this.mTempParentRect);
        }
        this.mView.getLocationOnScreen(this.mTempGlobalRect);
        int offsetX = this.mTempGlobalRect[0];
        int offsetY = this.mTempGlobalRect[1];
        this.mTempScreenRect.set(this.mTempParentRect);
        this.mTempScreenRect.offset(offsetX, offsetY);
        node.setBoundsInScreen(this.mTempScreenRect);
        return node;
    }
}
 
源代码5 项目: brailleback   文件: TreeDebug.java
/**
 * Gets a description of the properties of a node.
 */
public static CharSequence nodeDebugDescription(AccessibilityNodeInfoCompat node) {
    StringBuilder sb = new StringBuilder();
    sb.append(node.getWindowId());

    if (node.getClassName() != null) {
        appendSimpleName(sb, node.getClassName());
    } else {
        sb.append("??");
    }

    if (!node.isVisibleToUser()) {
        sb.append(":invisible");
    }

    if (node.getText() != null) {
        sb.append(":");
        sb.append(node.getText().toString().trim());
    }

    if (node.getContentDescription() != null) {
        sb.append(":");
        sb.append(node.getContentDescription().toString().trim());
    }

    int actions = node.getActions();
    if (actions != 0) {
        sb.append(":");
        if ((actions & AccessibilityNodeInfoCompat.ACTION_FOCUS) != 0) {
            sb.append("F");
        }
        if ((actions & AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS) != 0) {
            sb.append("A");
        }
        if ((actions & AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
            sb.append("a");
        }
        if ((actions & AccessibilityNodeInfoCompat.ACTION_SCROLL_BACKWARD) != 0) {
            sb.append("-");
        }
        if ((actions & AccessibilityNodeInfoCompat.ACTION_SCROLL_FORWARD) != 0) {
            sb.append("+");
        }
    }

    if (node.isCheckable()) {
        sb.append(":");
        if (node.isChecked()) {
            sb.append("(X)");
        } else {
            sb.append("( )");
        }
    }

    if (node.isFocusable()) {
        sb.append(":focusable");
    }

    if (node.isFocused()) {
        sb.append(":focused");
    }

    if (node.isSelected()) {
        sb.append(":selected");
    }

    if (node.isClickable()) {
        sb.append(":clickable");
    }

    if (node.isLongClickable()) {
        sb.append(":longClickable");
    }

    if (node.isAccessibilityFocused()) {
        sb.append(":accessibilityFocused");
    }

    if (!node.isEnabled()) {
        sb.append(":disabled");
    }

    return sb.toString();
}
 
源代码6 项目: stetho   文件: AccessibilityNodeInfoWrapper.java
@Nullable
public static CharSequence getDescription(View view) {
  AccessibilityNodeInfoCompat node = createNodeInfoFromView(view);
  try {
    CharSequence contentDescription = node.getContentDescription();
    CharSequence nodeText = node.getText();

    boolean hasNodeText = !TextUtils.isEmpty(nodeText);
    boolean isEditText = view instanceof EditText;

    // EditText's prioritize their own text content over a contentDescription
    if (!TextUtils.isEmpty(contentDescription) && (!isEditText || !hasNodeText)) {
      return contentDescription;
    }

    if (hasNodeText) {
      return nodeText;
    }

    // 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 String separator = ", ";
      ViewGroup viewGroup = (ViewGroup) view;

      for (int i = 0, count = viewGroup.getChildCount(); i < count; i++) {
        final View child = viewGroup.getChildAt(i);

        AccessibilityNodeInfoCompat childNodeInfo = AccessibilityNodeInfoCompat.obtain();
        ViewCompat.onInitializeAccessibilityNodeInfo(child, childNodeInfo);

        CharSequence childNodeDescription = null;
        if (AccessibilityUtil.isSpeakingNode(childNodeInfo, child) &&
            !AccessibilityUtil.isAccessibilityFocusable(childNodeInfo, child)) {
          childNodeDescription = getDescription(child);
        }

        if (!TextUtils.isEmpty(childNodeDescription)) {
          if (concatChildDescription.length() > 0) {
            concatChildDescription.append(separator);
          }
          concatChildDescription.append(childNodeDescription);
        }
        childNodeInfo.recycle();
      }

      return concatChildDescription.length() > 0 ? concatChildDescription.toString() : null;
    }

    return null;
  } finally {
    node.recycle();
  }
}
 
源代码7 项目: MiBandDecompiled   文件: ExploreByTouchHelper.java
private AccessibilityNodeInfoCompat d(int l)
{
    AccessibilityNodeInfoCompat accessibilitynodeinfocompat = AccessibilityNodeInfoCompat.obtain();
    accessibilitynodeinfocompat.setEnabled(true);
    accessibilitynodeinfocompat.setClassName(b);
    onPopulateNodeForVirtualView(l, accessibilitynodeinfocompat);
    if (accessibilitynodeinfocompat.getText() == null && accessibilitynodeinfocompat.getContentDescription() == null)
    {
        throw new RuntimeException("Callbacks must add text or a content description in populateNodeForVirtualViewId()");
    }
    accessibilitynodeinfocompat.getBoundsInParent(d);
    if (d.isEmpty())
    {
        throw new RuntimeException("Callbacks must set parent bounds in populateNodeForVirtualViewId()");
    }
    int i1 = accessibilitynodeinfocompat.getActions();
    if ((i1 & 0x40) != 0)
    {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in populateNodeForVirtualViewId()");
    }
    if ((i1 & 0x80) != 0)
    {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in populateNodeForVirtualViewId()");
    }
    accessibilitynodeinfocompat.setPackageName(h.getContext().getPackageName());
    accessibilitynodeinfocompat.setSource(h, l);
    accessibilitynodeinfocompat.setParent(h);
    int j1;
    int k1;
    if (j == l)
    {
        accessibilitynodeinfocompat.setAccessibilityFocused(true);
        accessibilitynodeinfocompat.addAction(128);
    } else
    {
        accessibilitynodeinfocompat.setAccessibilityFocused(false);
        accessibilitynodeinfocompat.addAction(64);
    }
    if (a(d))
    {
        accessibilitynodeinfocompat.setVisibleToUser(true);
        accessibilitynodeinfocompat.setBoundsInParent(d);
    }
    h.getLocationOnScreen(f);
    j1 = f[0];
    k1 = f[1];
    c.set(d);
    c.offset(j1, k1);
    accessibilitynodeinfocompat.setBoundsInScreen(c);
    return accessibilitynodeinfocompat;
}
 
/**
 * Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
 * specified item. Automatically manages accessibility focus actions.
 * <p>
 * Allows the implementing class to specify most node properties, but
 * overrides the following:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setPackageName}
 * <li>{@link AccessibilityNodeInfoCompat#setClassName}
 * <li>{@link AccessibilityNodeInfoCompat#setParent(View)}
 * <li>{@link AccessibilityNodeInfoCompat#setSource(View, int)}
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)}
 * </ul>
 * <p>
 * Uses the bounds of the parent view and the parent-relative bounding
 * rectangle specified by
 * {@link AccessibilityNodeInfoCompat#getBoundsInParent} to automatically
 * update the following properties:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInParent}
 * </ul>
 *
 * @param virtualViewId The virtual view id for item for which to construct
 *            a node.
 * @return An {@link AccessibilityNodeInfoCompat} for the specified item.
 */
private AccessibilityNodeInfoCompat createNodeForChild(int virtualViewId) {
    final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();

    // Ensure the client has good defaults.
    node.setEnabled(true);
    node.setClassName(DEFAULT_CLASS_NAME);

    // Allow the client to populate the node.
    onPopulateNodeForVirtualView(virtualViewId, node);

    // Make sure the developer is following the rules.
    if ((node.getText() == null) && (node.getContentDescription() == null)) {
        throw new RuntimeException("Callbacks must add text or a content description in "
                + "populateNodeForVirtualViewId()");
    }

    node.getBoundsInParent(mTempParentRect);
    if (mTempParentRect.isEmpty()) {
        throw new RuntimeException("Callbacks must set parent bounds in "
                + "populateNodeForVirtualViewId()");
    }

    final int actions = node.getActions();
    if ((actions & AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }
    if ((actions & AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }

    // Don't allow the client to override these properties.
    node.setPackageName(mView.getContext().getPackageName());
    node.setSource(mView, virtualViewId);
    node.setParent(mView);

    // Manage internal accessibility focus state.
    if (mFocusedVirtualViewId == virtualViewId) {
        node.setAccessibilityFocused(true);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
    } else {
        node.setAccessibilityFocused(false);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
    }

    // Set the visibility based on the parent bound.
    if (intersectVisibleToUser(mTempParentRect)) {
        node.setVisibleToUser(true);
        node.setBoundsInParent(mTempParentRect);
    }

    // Calculate screen-relative bound.
    mView.getLocationOnScreen(mTempGlobalRect);
    final int offsetX = mTempGlobalRect[0];
    final int offsetY = mTempGlobalRect[1];
    mTempScreenRect.set(mTempParentRect);
    mTempScreenRect.offset(offsetX, offsetY);
    node.setBoundsInScreen(mTempScreenRect);

    return node;
}
 
/**
 * Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
 * specified item. Automatically manages accessibility focus actions.
 * <p>
 * Allows the implementing class to specify most node properties, but
 * overrides the following:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setPackageName}
 * <li>{@link AccessibilityNodeInfoCompat#setClassName}
 * <li>{@link AccessibilityNodeInfoCompat#setParent(View)}
 * <li>{@link AccessibilityNodeInfoCompat#setSource(View, int)}
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)}
 * </ul>
 * <p>
 * Uses the bounds of the parent view and the parent-relative bounding
 * rectangle specified by
 * {@link AccessibilityNodeInfoCompat#getBoundsInParent} to automatically
 * update the following properties:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInParent}
 * </ul>
 *
 * @param virtualViewId The virtual view id for item for which to construct
 *            a node.
 * @return An {@link AccessibilityNodeInfoCompat} for the specified item.
 */
private AccessibilityNodeInfoCompat createNodeForChild(int virtualViewId) {
    final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();

    // Ensure the client has good defaults.
    node.setEnabled(true);
    node.setClassName(DEFAULT_CLASS_NAME);

    // Allow the client to populate the node.
    onPopulateNodeForVirtualView(virtualViewId, node);

    // Make sure the developer is following the rules.
    if ((node.getText() == null) && (node.getContentDescription() == null)) {
        throw new RuntimeException("Callbacks must add text or a content description in "
                + "populateNodeForVirtualViewId()");
    }

    node.getBoundsInParent(mTempParentRect);
    if (mTempParentRect.isEmpty()) {
        throw new RuntimeException("Callbacks must set parent bounds in "
                + "populateNodeForVirtualViewId()");
    }

    final int actions = node.getActions();
    if ((actions & AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }
    if ((actions & AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }

    // Don't allow the client to override these properties.
    node.setPackageName(mView.getContext().getPackageName());
    node.setSource(mView, virtualViewId);
    node.setParent(mView);

    // Manage internal accessibility focus state.
    if (mFocusedVirtualViewId == virtualViewId) {
        node.setAccessibilityFocused(true);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
    } else {
        node.setAccessibilityFocused(false);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
    }

    // Set the visibility based on the parent bound.
    if (intersectVisibleToUser(mTempParentRect)) {
        node.setVisibleToUser(true);
        node.setBoundsInParent(mTempParentRect);
    }

    // Calculate screen-relative bound.
    mView.getLocationOnScreen(mTempGlobalRect);
    final int offsetX = mTempGlobalRect[0];
    final int offsetY = mTempGlobalRect[1];
    mTempScreenRect.set(mTempParentRect);
    mTempScreenRect.offset(offsetX, offsetY);
    node.setBoundsInScreen(mTempScreenRect);

    return node;
}
 
源代码10 项目: V.FlyoutTest   文件: ExploreByTouchHelper.java
/**
 * Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
 * specified item. Automatically manages accessibility focus actions.
 * <p>
 * Allows the implementing class to specify most node properties, but
 * overrides the following:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setPackageName}
 * <li>{@link AccessibilityNodeInfoCompat#setClassName}
 * <li>{@link AccessibilityNodeInfoCompat#setParent(View)}
 * <li>{@link AccessibilityNodeInfoCompat#setSource(View, int)}
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)}
 * </ul>
 * <p>
 * Uses the bounds of the parent view and the parent-relative bounding
 * rectangle specified by
 * {@link AccessibilityNodeInfoCompat#getBoundsInParent} to automatically
 * update the following properties:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInParent}
 * </ul>
 *
 * @param virtualViewId The virtual view id for item for which to construct
 *            a node.
 * @return An {@link AccessibilityNodeInfoCompat} for the specified item.
 */
private AccessibilityNodeInfoCompat createNodeForChild(int virtualViewId) {
    final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();

    // Ensure the client has good defaults.
    node.setEnabled(true);
    node.setClassName(DEFAULT_CLASS_NAME);

    // Allow the client to populate the node.
    onPopulateNodeForVirtualView(virtualViewId, node);

    // Make sure the developer is following the rules.
    if ((node.getText() == null) && (node.getContentDescription() == null)) {
        throw new RuntimeException("Callbacks must add text or a content description in "
                + "populateNodeForVirtualViewId()");
    }

    node.getBoundsInParent(mTempParentRect);
    if (mTempParentRect.isEmpty()) {
        throw new RuntimeException("Callbacks must set parent bounds in "
                + "populateNodeForVirtualViewId()");
    }

    final int actions = node.getActions();
    if ((actions & AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }
    if ((actions & AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }

    // Don't allow the client to override these properties.
    node.setPackageName(mView.getContext().getPackageName());
    node.setSource(mView, virtualViewId);
    node.setParent(mView);

    // Manage internal accessibility focus state.
    if (mFocusedVirtualViewId == virtualViewId) {
        node.setAccessibilityFocused(true);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
    } else {
        node.setAccessibilityFocused(false);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
    }

    // Set the visibility based on the parent bound.
    if (intersectVisibleToUser(mTempParentRect)) {
        node.setVisibleToUser(true);
        node.setBoundsInParent(mTempParentRect);
    }

    // Calculate screen-relative bound.
    mView.getLocationOnScreen(mTempGlobalRect);
    final int offsetX = mTempGlobalRect[0];
    final int offsetY = mTempGlobalRect[1];
    mTempScreenRect.set(mTempParentRect);
    mTempScreenRect.offset(offsetX, offsetY);
    node.setBoundsInScreen(mTempScreenRect);

    return node;
}
 
源代码11 项目: guideshow   文件: ExploreByTouchHelper.java
/**
 * Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
 * specified item. Automatically manages accessibility focus actions.
 * <p>
 * Allows the implementing class to specify most node properties, but
 * overrides the following:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setPackageName}
 * <li>{@link AccessibilityNodeInfoCompat#setClassName}
 * <li>{@link AccessibilityNodeInfoCompat#setParent(View)}
 * <li>{@link AccessibilityNodeInfoCompat#setSource(View, int)}
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)}
 * </ul>
 * <p>
 * Uses the bounds of the parent view and the parent-relative bounding
 * rectangle specified by
 * {@link AccessibilityNodeInfoCompat#getBoundsInParent} to automatically
 * update the following properties:
 * <ul>
 * <li>{@link AccessibilityNodeInfoCompat#setVisibleToUser}
 * <li>{@link AccessibilityNodeInfoCompat#setBoundsInParent}
 * </ul>
 *
 * @param virtualViewId The virtual view id for item for which to construct
 *            a node.
 * @return An {@link AccessibilityNodeInfoCompat} for the specified item.
 */
private AccessibilityNodeInfoCompat createNodeForChild(int virtualViewId) {
    final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain();

    // Ensure the client has good defaults.
    node.setEnabled(true);
    node.setClassName(DEFAULT_CLASS_NAME);

    // Allow the client to populate the node.
    onPopulateNodeForVirtualView(virtualViewId, node);

    // Make sure the developer is following the rules.
    if ((node.getText() == null) && (node.getContentDescription() == null)) {
        throw new RuntimeException("Callbacks must add text or a content description in "
                + "populateNodeForVirtualViewId()");
    }

    node.getBoundsInParent(mTempParentRect);
    if (mTempParentRect.isEmpty()) {
        throw new RuntimeException("Callbacks must set parent bounds in "
                + "populateNodeForVirtualViewId()");
    }

    final int actions = node.getActions();
    if ((actions & AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }
    if ((actions & AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS) != 0) {
        throw new RuntimeException("Callbacks must not add ACTION_CLEAR_ACCESSIBILITY_FOCUS in "
                + "populateNodeForVirtualViewId()");
    }

    // Don't allow the client to override these properties.
    node.setPackageName(mView.getContext().getPackageName());
    node.setSource(mView, virtualViewId);
    node.setParent(mView);

    // Manage internal accessibility focus state.
    if (mFocusedVirtualViewId == virtualViewId) {
        node.setAccessibilityFocused(true);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
    } else {
        node.setAccessibilityFocused(false);
        node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS);
    }

    // Set the visibility based on the parent bound.
    if (intersectVisibleToUser(mTempParentRect)) {
        node.setVisibleToUser(true);
        node.setBoundsInParent(mTempParentRect);
    }

    // Calculate screen-relative bound.
    mView.getLocationOnScreen(mTempGlobalRect);
    final int offsetX = mTempGlobalRect[0];
    final int offsetY = mTempGlobalRect[1];
    mTempScreenRect.set(mTempParentRect);
    mTempScreenRect.offset(offsetX, offsetY);
    node.setBoundsInScreen(mTempScreenRect);

    return node;
}