diff options
| -rw-r--r-- | api/current.txt | 2 | ||||
| -rw-r--r-- | api/system-current.txt | 2 | ||||
| -rw-r--r-- | api/test-current.txt | 2 | ||||
| -rw-r--r-- | core/java/android/view/View.java | 62 | ||||
| -rw-r--r-- | core/java/android/view/ViewGroup.java | 20 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityNodeInfo.java | 36 |
6 files changed, 124 insertions, 0 deletions
diff --git a/api/current.txt b/api/current.txt index 05c40d175e2f..09de87afa796 100644 --- a/api/current.txt +++ b/api/current.txt @@ -42762,6 +42762,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo getCollectionInfo(); method public android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo getCollectionItemInfo(); method public java.lang.CharSequence getContentDescription(); + method public int getDrawingOrder(); method public java.lang.CharSequence getError(); method public android.os.Bundle getExtras(); method public int getInputType(); @@ -42824,6 +42825,7 @@ package android.view.accessibility { method public void setContentInvalid(boolean); method public void setContextClickable(boolean); method public void setDismissable(boolean); + method public void setDrawingOrder(int); method public void setEditable(boolean); method public void setEnabled(boolean); method public void setError(java.lang.CharSequence); diff --git a/api/system-current.txt b/api/system-current.txt index fb47833cc3ba..049b67ac9e91 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -45124,6 +45124,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo getCollectionInfo(); method public android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo getCollectionItemInfo(); method public java.lang.CharSequence getContentDescription(); + method public int getDrawingOrder(); method public java.lang.CharSequence getError(); method public android.os.Bundle getExtras(); method public int getInputType(); @@ -45186,6 +45187,7 @@ package android.view.accessibility { method public void setContentInvalid(boolean); method public void setContextClickable(boolean); method public void setDismissable(boolean); + method public void setDrawingOrder(int); method public void setEditable(boolean); method public void setEnabled(boolean); method public void setError(java.lang.CharSequence); diff --git a/api/test-current.txt b/api/test-current.txt index 3fb9b5f06b8f..d7fbba7855db 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -42778,6 +42778,7 @@ package android.view.accessibility { method public android.view.accessibility.AccessibilityNodeInfo.CollectionInfo getCollectionInfo(); method public android.view.accessibility.AccessibilityNodeInfo.CollectionItemInfo getCollectionItemInfo(); method public java.lang.CharSequence getContentDescription(); + method public int getDrawingOrder(); method public java.lang.CharSequence getError(); method public android.os.Bundle getExtras(); method public int getInputType(); @@ -42840,6 +42841,7 @@ package android.view.accessibility { method public void setContentInvalid(boolean); method public void setContextClickable(boolean); method public void setDismissable(boolean); + method public void setDrawingOrder(int); method public void setEditable(boolean); method public void setEnabled(boolean); method public void setError(java.lang.CharSequence); diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index 0316506b94c4..c22f71001894 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -6691,6 +6691,68 @@ public class View implements Drawable.Callback, KeyEvent.Callback, } info.addAction(AccessibilityAction.ACTION_SHOW_ON_SCREEN); + populateAccessibilityNodeInfoDrawingOrderInParent(info); + } + + /** + * Determine the order in which this view will be drawn relative to its siblings for a11y + * + * @param info The info whose drawing order should be populated + */ + private void populateAccessibilityNodeInfoDrawingOrderInParent(AccessibilityNodeInfo info) { + int drawingOrderInParent = 1; + // Iterate up the hierarchy if parents are not important for a11y + View viewAtDrawingLevel = this; + final ViewParent parent = getParentForAccessibility(); + while (viewAtDrawingLevel != parent) { + final ViewParent currentParent = viewAtDrawingLevel.getParent(); + if (!(currentParent instanceof ViewGroup)) { + // Should only happen for the Decor + drawingOrderInParent = 0; + break; + } else { + final ViewGroup parentGroup = (ViewGroup) currentParent; + final int childCount = parentGroup.getChildCount(); + if (childCount > 1) { + List<View> preorderedList = parentGroup.buildOrderedChildList(); + if (preorderedList != null) { + final int childDrawIndex = preorderedList.indexOf(viewAtDrawingLevel); + for (int i = 0; i < childDrawIndex; i++) { + drawingOrderInParent += numViewsForAccessibility(preorderedList.get(i)); + } + } else { + final int childIndex = parentGroup.indexOfChild(viewAtDrawingLevel); + final boolean customOrder = parentGroup.isChildrenDrawingOrderEnabled(); + final int childDrawIndex = ((childIndex >= 0) && customOrder) ? parentGroup + .getChildDrawingOrder(childCount, childIndex) : childIndex; + final int numChildrenToIterate = customOrder ? childCount : childDrawIndex; + if (childDrawIndex != 0) { + for (int i = 0; i < numChildrenToIterate; i++) { + final int otherDrawIndex = (customOrder ? + parentGroup.getChildDrawingOrder(childCount, i) : i); + if (otherDrawIndex < childDrawIndex) { + drawingOrderInParent += + numViewsForAccessibility(parentGroup.getChildAt(i)); + } + } + } + } + } + } + viewAtDrawingLevel = (View) currentParent; + } + info.setDrawingOrder(drawingOrderInParent); + } + + private static int numViewsForAccessibility(View view) { + if (view != null) { + if (view.includeForAccessibility()) { + return 1; + } else if (view instanceof ViewGroup) { + return ((ViewGroup) view).getNumChildrenForAccessibility(); + } + } + return 0; } private View findLabelForView(View view, int labeledId) { diff --git a/core/java/android/view/ViewGroup.java b/core/java/android/view/ViewGroup.java index f674298d3774..2fd4d835d35f 100644 --- a/core/java/android/view/ViewGroup.java +++ b/core/java/android/view/ViewGroup.java @@ -3083,6 +3083,26 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager } /** + * Counts the number of children of this View that will be sent to an accessibility service. + * + * @return The number of children an {@code AccessibilityNodeInfo} rooted at this View + * would have. + */ + int getNumChildrenForAccessibility() { + int numChildrenForAccessibility = 0; + for (int i = 0; i < getChildCount(); i++) { + View child = getChildAt(i); + if (child.includeForAccessibility()) { + numChildrenForAccessibility++; + } else if (child instanceof ViewGroup) { + numChildrenForAccessibility += ((ViewGroup) child) + .getNumChildrenForAccessibility(); + } + } + return numChildrenForAccessibility; + } + + /** * {@inheritDoc} * * <p>Subclasses should always call <code>super.onNestedPrePerformAccessibilityAction</code></p> diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 1735e1b9e829..1327ea1c2f56 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -647,6 +647,7 @@ public class AccessibilityNodeInfo implements Parcelable { private int mBooleanProperties; private final Rect mBoundsInParent = new Rect(); private final Rect mBoundsInScreen = new Rect(); + private int mDrawingOrderInParent; private CharSequence mPackageName; private CharSequence mClassName; @@ -1892,6 +1893,37 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Get the drawing order of the view corresponding it this node. + * <p> + * Drawing order is determined only within the node's parent, so this index is only relative + * to its siblings. + * <p> + * In some cases, the drawing order is essentially simultaneous, so it is possible for two + * siblings to return the same value. It is also possible that values will be skipped. + * + * @return The drawing position of the view corresponding to this node relative to its siblings. + */ + public int getDrawingOrder() { + return mDrawingOrderInParent; + } + + /** + * Set the drawing order of the view corresponding it this node. + * + * <p> + * <strong>Note:</strong> Cannot be called from an + * {@link android.accessibilityservice.AccessibilityService}. + * This class is made immutable before being delivered to an AccessibilityService. + * </p> + * @param drawingOrderInParent + * @throws IllegalStateException If called from an AccessibilityService. + */ + public void setDrawingOrder(int drawingOrderInParent) { + enforceNotSealed(); + mDrawingOrderInParent = drawingOrderInParent; + } + + /** * Gets the collection info if the node is a collection. A collection * child is always a collection item. * @@ -2753,6 +2785,7 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeInt(mTextSelectionEnd); parcel.writeInt(mInputType); parcel.writeInt(mLiveRegion); + parcel.writeInt(mDrawingOrderInParent); if (mExtras != null) { parcel.writeInt(1); @@ -2850,6 +2883,7 @@ public class AccessibilityNodeInfo implements Parcelable { mTextSelectionEnd = other.mTextSelectionEnd; mInputType = other.mInputType; mLiveRegion = other.mLiveRegion; + mDrawingOrderInParent = other.mDrawingOrderInParent; if (other.mExtras != null && !other.mExtras.isEmpty()) { getExtras().putAll(other.mExtras); } @@ -2927,6 +2961,7 @@ public class AccessibilityNodeInfo implements Parcelable { mInputType = parcel.readInt(); mLiveRegion = parcel.readInt(); + mDrawingOrderInParent = parcel.readInt(); if (parcel.readInt() == 1) { getExtras().putAll(parcel.readBundle()); @@ -2982,6 +3017,7 @@ public class AccessibilityNodeInfo implements Parcelable { mBoundsInParent.set(0, 0, 0, 0); mBoundsInScreen.set(0, 0, 0, 0); mBooleanProperties = 0; + mDrawingOrderInParent = 0; mPackageName = null; mClassName = null; mText = null; |