Merge "Add API for nested pre-processing of a11y events; fix ResolverDrawerLayout" into lmp-mr1-dev

This commit is contained in:
Adam Powell
2015-01-13 18:57:32 +00:00
committed by Android (Google) Code Review
6 changed files with 145 additions and 0 deletions

View File

@@ -33332,6 +33332,7 @@ package android.view {
method public boolean dispatchKeyShortcutEvent(android.view.KeyEvent);
method public boolean dispatchNestedFling(float, float, boolean);
method public boolean dispatchNestedPreFling(float, float);
method public boolean dispatchNestedPrePerformAccessibilityAction(int, android.os.Bundle);
method public boolean dispatchNestedPreScroll(int, int, int[], int[]);
method public boolean dispatchNestedScroll(int, int, int, int, int[]);
method public boolean dispatchPopulateAccessibilityEvent(android.view.accessibility.AccessibilityEvent);
@@ -34144,6 +34145,7 @@ package android.view {
method protected abstract void onLayout(boolean, int, int, int, int);
method public boolean onNestedFling(android.view.View, float, float, boolean);
method public boolean onNestedPreFling(android.view.View, float, float);
method public boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
method public void onNestedPreScroll(android.view.View, int, int, int[]);
method public void onNestedScroll(android.view.View, int, int, int, int);
method public void onNestedScrollAccepted(android.view.View, android.view.View, int);
@@ -34292,6 +34294,7 @@ package android.view {
method public abstract void notifySubtreeAccessibilityStateChanged(android.view.View, android.view.View, int);
method public abstract boolean onNestedFling(android.view.View, float, float, boolean);
method public abstract boolean onNestedPreFling(android.view.View, float, float);
method public abstract boolean onNestedPrePerformAccessibilityAction(android.view.View, int, android.os.Bundle);
method public abstract void onNestedPreScroll(android.view.View, int, int, int[]);
method public abstract void onNestedScroll(android.view.View, int, int, int, int);
method public abstract void onNestedScrollAccepted(android.view.View, android.view.View, int);

View File

@@ -8158,6 +8158,34 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
mPrivateFlags2 &= ~PFLAG2_SUBTREE_ACCESSIBILITY_STATE_CHANGED;
}
/**
* Report an accessibility action to this view's parents for delegated processing.
*
* <p>Implementations of {@link #performAccessibilityAction(int, Bundle)} may internally
* call this method to delegate an accessibility action to a supporting parent. If the parent
* returns true from its
* {@link ViewParent#onNestedPrePerformAccessibilityAction(View, int, android.os.Bundle)}
* method this method will return true to signify that the action was consumed.</p>
*
* <p>This method is useful for implementing nested scrolling child views. If
* {@link #isNestedScrollingEnabled()} returns true and the action is a scrolling action
* a custom view implementation may invoke this method to allow a parent to consume the
* scroll first. If this method returns true the custom view should skip its own scrolling
* behavior.</p>
*
* @param action Accessibility action to delegate
* @param arguments Optional action arguments
* @return true if the action was consumed by a parent
*/
public boolean dispatchNestedPrePerformAccessibilityAction(int action, Bundle arguments) {
for (ViewParent p = getParent(); p != null; p = p.getParent()) {
if (p.onNestedPrePerformAccessibilityAction(this, action, arguments)) {
return true;
}
}
return false;
}
/**
* Performs the specified accessibility action on the view. For
* possible accessibility actions look at {@link AccessibilityNodeInfo}.
@@ -8168,6 +8196,11 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* is responsible for handling this call.
* </p>
*
* <p>The default implementation will delegate
* {@link AccessibilityNodeInfo#ACTION_SCROLL_BACKWARD} and
* {@link AccessibilityNodeInfo#ACTION_SCROLL_FORWARD} to nested scrolling parents if
* {@link #isNestedScrollingEnabled() nested scrolling is enabled} on this view.</p>
*
* @param action The action to perform.
* @param arguments Optional action arguments.
* @return Whether the action was performed.
@@ -8188,6 +8221,14 @@ public class View implements Drawable.Callback, KeyEvent.Callback,
* @hide Until we've refactored all accessibility delegation methods.
*/
public boolean performAccessibilityActionInternal(int action, Bundle arguments) {
if (isNestedScrollingEnabled()
&& (action == AccessibilityNodeInfo.ACTION_SCROLL_BACKWARD
|| action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD)) {
if (dispatchNestedPrePerformAccessibilityAction(action, arguments)) {
return true;
}
}
switch (action) {
case AccessibilityNodeInfo.ACTION_CLICK: {
if (isClickable()) {

View File

@@ -32,6 +32,7 @@ import android.graphics.Rect;
import android.graphics.RectF;
import android.graphics.Region;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.os.SystemClock;
import android.util.AttributeSet;
@@ -2921,6 +2922,22 @@ public abstract class ViewGroup extends View implements ViewParent, ViewManager
}
}
/**
* {@inheritDoc}
*
* <p>Subclasses should always call <code>super.onNestedPrePerformAccessibilityAction</code></p>
*
* @param target The target view dispatching this action
* @param action Action being performed; see
* {@link android.view.accessibility.AccessibilityNodeInfo}
* @param args Optional action arguments
* @return false by default. Subclasses should return true if they handle the event.
*/
@Override
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
return false;
}
/**
* {@inheritDoc}
*/

View File

@@ -17,6 +17,7 @@
package android.view;
import android.graphics.Rect;
import android.os.Bundle;
import android.view.accessibility.AccessibilityEvent;
/**
@@ -551,4 +552,23 @@ public interface ViewParent {
* @return true if this parent consumed the fling ahead of the target view
*/
public boolean onNestedPreFling(View target, float velocityX, float velocityY);
/**
* React to an accessibility action delegated by a target descendant view before the target
* processes it.
*
* <p>This method may be called by a target descendant view if the target wishes to give
* a view in its parent chain a chance to react to the event before normal processing occurs.
* Most commonly this will be a scroll event such as
* {@link android.view.accessibility.AccessibilityNodeInfo#ACTION_SCROLL_FORWARD}.
* A ViewParent that supports acting as a nested scrolling parent should override this
* method and act accordingly to implement scrolling via accesibility systems.</p>
*
* @param target The target view dispatching this action
* @param action Action being performed; see
* {@link android.view.accessibility.AccessibilityNodeInfo}
* @param arguments Optional action arguments
* @return true if the action was consumed by this ViewParent
*/
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle arguments);
}

View File

@@ -6417,6 +6417,11 @@ public final class ViewRootImpl implements ViewParent,
return false;
}
@Override
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
return false;
}
void changeCanvasOpacity(boolean opaque) {
Log.d(TAG, "changeCanvasOpacity: opaque=" + opaque);
if (mAttachInfo.mHardwareRenderer != null) {

View File

@@ -20,6 +20,7 @@ package com.android.internal.widget;
import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Rect;
import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcelable;
import android.util.AttributeSet;
@@ -31,6 +32,8 @@ import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.ViewParent;
import android.view.ViewTreeObserver;
import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityNodeInfo;
import android.view.animation.AnimationUtils;
import android.widget.AbsListView;
import android.widget.OverScroller;
@@ -367,8 +370,14 @@ public class ResolverDrawerLayout extends ViewGroup {
child.offsetTopAndBottom((int) dy);
}
}
final boolean isCollapsedOld = mCollapseOffset != 0;
mCollapseOffset = newPos;
mTopOffset += dy;
final boolean isCollapsedNew = newPos != 0;
if (isCollapsedOld != isCollapsedNew) {
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
postInvalidateOnAnimation();
return dy;
}
@@ -570,6 +579,50 @@ public class ResolverDrawerLayout extends ViewGroup {
return false;
}
@Override
public boolean onNestedPrePerformAccessibilityAction(View target, int action, Bundle args) {
if (super.onNestedPrePerformAccessibilityAction(target, action, args)) {
return true;
}
if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) {
smoothScrollTo(0, 0);
return true;
}
return false;
}
@Override
public void onInitializeAccessibilityEvent(AccessibilityEvent event) {
super.onInitializeAccessibilityEvent(event);
event.setClassName(ResolverDrawerLayout.class.getName());
}
@Override
public void onInitializeAccessibilityNodeInfo(AccessibilityNodeInfo info) {
super.onInitializeAccessibilityNodeInfo(info);
info.setClassName(ResolverDrawerLayout.class.getName());
if (isEnabled()) {
if (mCollapseOffset != 0) {
info.addAction(AccessibilityNodeInfo.ACTION_SCROLL_FORWARD);
info.setScrollable(true);
}
}
}
@Override
public boolean performAccessibilityAction(int action, Bundle arguments) {
if (super.performAccessibilityAction(action, arguments)) {
return true;
}
if (action == AccessibilityNodeInfo.ACTION_SCROLL_FORWARD && mCollapseOffset != 0) {
smoothScrollTo(0, 0);
return true;
}
return false;
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
final int sourceWidth = MeasureSpec.getSize(widthMeasureSpec);
@@ -615,7 +668,13 @@ public class ResolverDrawerLayout extends ViewGroup {
mUncollapsibleHeight = heightUsed - mCollapsibleHeight;
if (isLaidOut()) {
final boolean isCollapsedOld = mCollapseOffset != 0;
mCollapseOffset = Math.min(mCollapseOffset, mCollapsibleHeight);
final boolean isCollapsedNew = mCollapseOffset != 0;
if (isCollapsedOld != isCollapsedNew) {
notifyViewAccessibilityStateChangedIfNeeded(
AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED);
}
} else {
// Start out collapsed at first unless we restored state for otherwise
mCollapseOffset = mOpenOnLayout ? 0 : mCollapsibleHeight;