Methods Summary |
---|
private boolean | clearAccessibilityFocus(int virtualViewId)Attempts to clear accessibility focus from a virtual view.
if (isAccessibilityFocused(virtualViewId)) {
mFocusedVirtualViewId = INVALID_ID;
mView.invalidate();
sendEventForVirtualView(virtualViewId,
AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
return true;
}
return false;
|
private android.view.accessibility.AccessibilityEvent | createEvent(int virtualViewId, int eventType)Constructs and returns an {@link AccessibilityEvent} for the specified
virtual view id, which includes the host view ({@link View#NO_ID}).
switch (virtualViewId) {
case View.NO_ID:
return createEventForHost(eventType);
default:
return createEventForChild(virtualViewId, eventType);
}
|
private android.view.accessibility.AccessibilityEvent | createEventForChild(int virtualViewId, int eventType)Constructs and returns an {@link AccessibilityEvent} populated with
information about the specified item.
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
event.setEnabled(true);
event.setClassName(DEFAULT_CLASS_NAME);
// Allow the client to populate the event.
onPopulateEventForVirtualView(virtualViewId, event);
// Make sure the developer is following the rules.
if (event.getText().isEmpty() && (event.getContentDescription() == null)) {
throw new RuntimeException("Callbacks must add text or a content description in "
+ "populateEventForVirtualViewId()");
}
// Don't allow the client to override these properties.
event.setPackageName(mView.getContext().getPackageName());
final AccessibilityRecordCompat record = AccessibilityEventCompat.asRecord(event);
record.setSource(mView, virtualViewId);
return event;
|
private android.view.accessibility.AccessibilityEvent | createEventForHost(int eventType)Constructs and returns an {@link AccessibilityEvent} for the host node.
final AccessibilityEvent event = AccessibilityEvent.obtain(eventType);
ViewCompat.onInitializeAccessibilityEvent(mView, event);
return event;
|
private android.support.v4.view.accessibility.AccessibilityNodeInfoCompat | createNode(int virtualViewId)Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
specified virtual view id, which includes the host view
({@link View#NO_ID}).
switch (virtualViewId) {
case View.NO_ID:
return createNodeForHost();
default:
return createNodeForChild(virtualViewId);
}
|
private android.support.v4.view.accessibility.AccessibilityNodeInfoCompat | createNodeForChild(int virtualViewId)Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
specified item. Automatically manages accessibility focus actions.
Allows the implementing class to specify most node properties, but
overrides the following:
- {@link AccessibilityNodeInfoCompat#setPackageName}
- {@link AccessibilityNodeInfoCompat#setClassName}
- {@link AccessibilityNodeInfoCompat#setParent(View)}
- {@link AccessibilityNodeInfoCompat#setSource(View, int)}
- {@link AccessibilityNodeInfoCompat#setVisibleToUser}
- {@link AccessibilityNodeInfoCompat#setBoundsInScreen(Rect)}
Uses the bounds of the parent view and the parent-relative bounding
rectangle specified by
{@link AccessibilityNodeInfoCompat#getBoundsInParent} to automatically
update the following properties:
- {@link AccessibilityNodeInfoCompat#setVisibleToUser}
- {@link AccessibilityNodeInfoCompat#setBoundsInParent}
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;
|
private android.support.v4.view.accessibility.AccessibilityNodeInfoCompat | createNodeForHost()Constructs and returns an {@link AccessibilityNodeInfoCompat} for the
host view populated with its virtual descendants.
final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain(mView);
ViewCompat.onInitializeAccessibilityNodeInfo(mView, node);
// Add the virtual descendants.
final LinkedList<Integer> virtualViewIds = new LinkedList<Integer>();
getVisibleVirtualViews(virtualViewIds);
for (Integer childVirtualViewId : virtualViewIds) {
node.addChild(mView, childVirtualViewId);
}
return node;
|
public boolean | dispatchHoverEvent(android.view.MotionEvent event)Dispatches hover {@link MotionEvent}s to the virtual view hierarchy when
the Explore by Touch feature is enabled.
This method should be called by overriding
{@link View#dispatchHoverEvent}:
@Override
public boolean dispatchHoverEvent(MotionEvent event) {
if (mHelper.dispatchHoverEvent(this, event) {
return true;
}
return super.dispatchHoverEvent(event);
}
if (!mManager.isEnabled()
|| !AccessibilityManagerCompat.isTouchExplorationEnabled(mManager)) {
return false;
}
switch (event.getAction()) {
case MotionEventCompat.ACTION_HOVER_MOVE:
case MotionEventCompat.ACTION_HOVER_ENTER:
final int virtualViewId = getVirtualViewAt(event.getX(), event.getY());
updateHoveredVirtualView(virtualViewId);
return (virtualViewId != INVALID_ID);
case MotionEventCompat.ACTION_HOVER_EXIT:
if (mFocusedVirtualViewId != INVALID_ID) {
updateHoveredVirtualView(INVALID_ID);
return true;
}
return false;
default:
return false;
}
|
public android.support.v4.view.accessibility.AccessibilityNodeProviderCompat | getAccessibilityNodeProvider(android.view.View host)Returns the {@link AccessibilityNodeProviderCompat} for this helper.
if (mNodeProvider == null) {
mNodeProvider = new ExploreByTouchNodeProvider();
}
return mNodeProvider;
|
public int | getFocusedVirtualView()Returns the virtual view id for the currently focused item,
return mFocusedVirtualViewId;
|
protected abstract int | getVirtualViewAt(float x, float y)Provides a mapping between view-relative coordinates and logical
items.
|
protected abstract void | getVisibleVirtualViews(java.util.List virtualViewIds)Populates a list with the view's visible items. The ordering of items
within {@code virtualViewIds} specifies order of accessibility focus
traversal.
|
private boolean | intersectVisibleToUser(android.graphics.Rect localRect)Computes whether the specified {@link Rect} intersects with the visible
portion of its parent {@link View}. Modifies {@code localRect} to contain
only the visible portion.
// Missing or empty bounds mean this view is not visible.
if ((localRect == null) || localRect.isEmpty()) {
return false;
}
// Attached to invisible window means this view is not visible.
if (mView.getWindowVisibility() != View.VISIBLE) {
return false;
}
// An invisible predecessor means that this view is not visible.
ViewParent viewParent = mView.getParent();
while (viewParent instanceof View) {
final View view = (View) viewParent;
if ((ViewCompat.getAlpha(view) <= 0) || (view.getVisibility() != View.VISIBLE)) {
return false;
}
viewParent = view.getParent();
}
// A null parent implies the view is not visible.
if (viewParent == null) {
return false;
}
// If no portion of the parent is visible, this view is not visible.
if (!mView.getLocalVisibleRect(mTempVisibleRect)) {
return false;
}
// Check if the view intersects the visible portion of the parent.
return localRect.intersect(mTempVisibleRect);
|
public void | invalidateRoot()Notifies the accessibility framework that the properties of the parent
view have changed.
You must call this method after adding or removing items from the
parent view.
invalidateVirtualView(View.NO_ID);
|
public void | invalidateVirtualView(int virtualViewId)Notifies the accessibility framework that the properties of a particular
item have changed.
You must call this method after changing any of the properties set
in {@link #onPopulateNodeForVirtualView}.
sendEventForVirtualView(
virtualViewId, AccessibilityEventCompat.TYPE_WINDOW_CONTENT_CHANGED);
|
private boolean | isAccessibilityFocused(int virtualViewId)Returns whether this virtual view is accessibility focused.
return (mFocusedVirtualViewId == virtualViewId);
|
private boolean | manageFocusForChild(int virtualViewId, int action, android.os.Bundle arguments)
switch (action) {
case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
return requestAccessibilityFocus(virtualViewId);
case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
return clearAccessibilityFocus(virtualViewId);
default:
return false;
}
|
protected abstract boolean | onPerformActionForVirtualView(int virtualViewId, int action, android.os.Bundle arguments)Performs the specified accessibility action on the item associated
with the virtual view identifier. See
{@link AccessibilityNodeInfoCompat#performAction(int, Bundle)} for
more information.
Implementations must handle any actions added manually in
{@link #onPopulateNodeForVirtualView}.
The helper class automatically handles focus management resulting
from {@link AccessibilityNodeInfoCompat#ACTION_ACCESSIBILITY_FOCUS}
and
{@link AccessibilityNodeInfoCompat#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
actions.
|
protected abstract void | onPopulateEventForVirtualView(int virtualViewId, android.view.accessibility.AccessibilityEvent event)Populates an {@link AccessibilityEvent} with information about the
specified item.
Implementations must populate the following required fields:
- event text, see {@link AccessibilityEvent#getText} or
{@link AccessibilityEvent#setContentDescription}
The helper class automatically populates the following fields with
default values, but implementations may optionally override them:
- item class name, set to android.view.View, see
{@link AccessibilityEvent#setClassName}
The following required fields are automatically populated by the
helper class and may not be overridden:
- package name, set to the package of the host view's
{@link Context}, see {@link AccessibilityEvent#setPackageName}
- event source, set to the host view and virtual view identifier,
see {@link AccessibilityRecordCompat#setSource(View, int)}
|
protected abstract void | onPopulateNodeForVirtualView(int virtualViewId, android.support.v4.view.accessibility.AccessibilityNodeInfoCompat node)Populates an {@link AccessibilityNodeInfoCompat} with information
about the specified item.
Implementations must populate the following required fields:
- event text, see {@link AccessibilityNodeInfoCompat#setText} or
{@link AccessibilityNodeInfoCompat#setContentDescription}
- bounds in parent coordinates, see
{@link AccessibilityNodeInfoCompat#setBoundsInParent}
The helper class automatically populates the following fields with
default values, but implementations may optionally override them:
- enabled state, set to true, see
{@link AccessibilityNodeInfoCompat#setEnabled}
- item class name, identical to the class name set by
{@link #onPopulateEventForVirtualView}, see
{@link AccessibilityNodeInfoCompat#setClassName}
The following required fields are automatically populated by the
helper class and may not be overridden:
- package name, identical to the package name set by
{@link #onPopulateEventForVirtualView}, see
{@link AccessibilityNodeInfoCompat#setPackageName}
- node source, identical to the event source set in
{@link #onPopulateEventForVirtualView}, see
{@link AccessibilityNodeInfoCompat#setSource(View, int)}
- parent view, set to the host view, see
{@link AccessibilityNodeInfoCompat#setParent(View)}
- visibility, computed based on parent-relative bounds, see
{@link AccessibilityNodeInfoCompat#setVisibleToUser}
- accessibility focus, computed based on internal helper state, see
{@link AccessibilityNodeInfoCompat#setAccessibilityFocused}
- bounds in screen coordinates, computed based on host view bounds,
see {@link AccessibilityNodeInfoCompat#setBoundsInScreen}
Additionally, the helper class automatically handles accessibility
focus management by adding the appropriate
{@link AccessibilityNodeInfoCompat#ACTION_ACCESSIBILITY_FOCUS} or
{@link AccessibilityNodeInfoCompat#ACTION_CLEAR_ACCESSIBILITY_FOCUS}
action. Implementations must never manually add these actions.
The helper class also automatically modifies parent- and
screen-relative bounds to reflect the portion of the item visible
within its parent.
|
private boolean | performAction(int virtualViewId, int action, android.os.Bundle arguments)
switch (virtualViewId) {
case View.NO_ID:
return performActionForHost(action, arguments);
default:
return performActionForChild(virtualViewId, action, arguments);
}
|
private boolean | performActionForChild(int virtualViewId, int action, android.os.Bundle arguments)
switch (action) {
case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS:
case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS:
return manageFocusForChild(virtualViewId, action, arguments);
default:
return onPerformActionForVirtualView(virtualViewId, action, arguments);
}
|
private boolean | performActionForHost(int action, android.os.Bundle arguments)
return ViewCompat.performAccessibilityAction(mView, action, arguments);
|
private boolean | requestAccessibilityFocus(int virtualViewId)Attempts to give accessibility focus to a virtual view.
A virtual view will not actually take focus if
{@link AccessibilityManager#isEnabled()} returns false,
{@link AccessibilityManager#isTouchExplorationEnabled()} returns false,
or the view already has accessibility focus.
if (!mManager.isEnabled()
|| !AccessibilityManagerCompat.isTouchExplorationEnabled(mManager)) {
return false;
}
// TODO: Check virtual view visibility.
if (!isAccessibilityFocused(virtualViewId)) {
mFocusedVirtualViewId = virtualViewId;
// TODO: Only invalidate virtual view bounds.
mView.invalidate();
sendEventForVirtualView(virtualViewId,
AccessibilityEventCompat.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
return true;
}
return false;
|
public boolean | sendEventForVirtualView(int virtualViewId, int eventType)Populates an event of the specified type with information about an item
and attempts to send it up through the view hierarchy.
You should call this method after performing a user action that normally
fires an accessibility event, such as clicking on an item.
public void performItemClick(T item) {
...
sendEventForVirtualViewId(item.id, AccessibilityEvent.TYPE_VIEW_CLICKED);
}
if ((virtualViewId == INVALID_ID) || !mManager.isEnabled()) {
return false;
}
final ViewParent parent = mView.getParent();
if (parent == null) {
return false;
}
final AccessibilityEvent event = createEvent(virtualViewId, eventType);
return ViewParentCompat.requestSendAccessibilityEvent(parent, mView, event);
|
private void | updateHoveredVirtualView(int virtualViewId)Sets the currently hovered item, sending hover accessibility events as
necessary to maintain the correct state.
if (mHoveredVirtualViewId == virtualViewId) {
return;
}
final int previousVirtualViewId = mHoveredVirtualViewId;
mHoveredVirtualViewId = virtualViewId;
// Stay consistent with framework behavior by sending ENTER/EXIT pairs
// in reverse order. This is accurate as of API 18.
sendEventForVirtualView(virtualViewId, AccessibilityEventCompat.TYPE_VIEW_HOVER_ENTER);
sendEventForVirtualView(
previousVirtualViewId, AccessibilityEventCompat.TYPE_VIEW_HOVER_EXIT);
|