Merge "Accessibility focus traversal in virtual nodes." into jb-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
0e29ac9e4e
@@ -491,20 +491,28 @@ final class AccessibilityInteractionController {
|
||||
if ((direction & View.FOCUS_ACCESSIBILITY) == View.FOCUS_ACCESSIBILITY) {
|
||||
AccessibilityNodeProvider provider = root.getAccessibilityNodeProvider();
|
||||
if (provider != null) {
|
||||
next = provider.accessibilityFocusSearch(direction,
|
||||
virtualDescendantId);
|
||||
} else if (virtualDescendantId == View.NO_ID) {
|
||||
View nextView = root.focusSearch(direction);
|
||||
if (nextView != null) {
|
||||
// If the focus search reached a node with a provider
|
||||
// we delegate to the provider to find the next one.
|
||||
provider = nextView.getAccessibilityNodeProvider();
|
||||
if (provider != null) {
|
||||
next = provider.accessibilityFocusSearch(direction,
|
||||
virtualDescendantId);
|
||||
} else {
|
||||
next = nextView.createAccessibilityNodeInfo();
|
||||
}
|
||||
next = provider.accessibilityFocusSearch(direction, virtualDescendantId);
|
||||
if (next != null) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
View nextView = root.focusSearch(direction);
|
||||
while (nextView != null) {
|
||||
// If the focus search reached a node with a provider
|
||||
// we delegate to the provider to find the next one.
|
||||
// If the provider does not return a virtual view to
|
||||
// take accessibility focus we try the next view found
|
||||
// by the focus search algorithm.
|
||||
provider = nextView.getAccessibilityNodeProvider();
|
||||
if (provider != null) {
|
||||
next = provider.accessibilityFocusSearch(direction, View.NO_ID);
|
||||
if (next != null) {
|
||||
break;
|
||||
}
|
||||
nextView = nextView.focusSearch(direction);
|
||||
} else {
|
||||
next = nextView.createAccessibilityNodeInfo();
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
||||
@@ -6027,7 +6027,7 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
|
||||
return;
|
||||
}
|
||||
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
|
||||
if (canTakeAccessibilityFocusFromHover()) {
|
||||
if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
|
||||
views.add(this);
|
||||
return;
|
||||
}
|
||||
@@ -6156,12 +6156,15 @@ public class View implements Drawable.Callback, Drawable.Callback2, KeyEvent.Cal
|
||||
* @hide
|
||||
*/
|
||||
public void clearAccessibilityFocus() {
|
||||
if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
|
||||
mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
|
||||
ViewRootImpl viewRootImpl = getViewRootImpl();
|
||||
if (viewRootImpl != null) {
|
||||
ViewRootImpl viewRootImpl = getViewRootImpl();
|
||||
if (viewRootImpl != null) {
|
||||
View focusHost = viewRootImpl.getAccessibilityFocusedHost();
|
||||
if (focusHost != null && ViewRootImpl.isViewDescendantOf(focusHost, this)) {
|
||||
viewRootImpl.setAccessibilityFocusedHost(null);
|
||||
}
|
||||
}
|
||||
if ((mPrivateFlags2 & ACCESSIBILITY_FOCUSED) != 0) {
|
||||
mPrivateFlags2 &= ~ACCESSIBILITY_FOCUSED;
|
||||
invalidate();
|
||||
sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||
notifyAccessibilityStateChanged();
|
||||
|
||||
@@ -488,7 +488,9 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mFallbackEventHandler.setView(view);
|
||||
mWindowAttributes.copyFrom(attrs);
|
||||
attrs = mWindowAttributes;
|
||||
|
||||
|
||||
setAccessibilityFocusedHost(null);
|
||||
|
||||
if (view instanceof RootViewSurfaceTaker) {
|
||||
mSurfaceHolderCallback =
|
||||
((RootViewSurfaceTaker)view).willYouTakeTheSurface();
|
||||
@@ -556,6 +558,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mInputChannel = null;
|
||||
mFallbackEventHandler.setView(null);
|
||||
unscheduleTraversals();
|
||||
setAccessibilityFocusedHost(null);
|
||||
throw new RuntimeException("Adding window failed", e);
|
||||
} finally {
|
||||
if (restore) {
|
||||
@@ -575,6 +578,7 @@ public final class ViewRootImpl implements ViewParent,
|
||||
mAdded = false;
|
||||
mFallbackEventHandler.setView(null);
|
||||
unscheduleTraversals();
|
||||
setAccessibilityFocusedHost(null);
|
||||
switch (res) {
|
||||
case WindowManagerImpl.ADD_BAD_APP_TOKEN:
|
||||
case WindowManagerImpl.ADD_BAD_SUBWINDOW_TOKEN:
|
||||
@@ -635,8 +639,6 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if (view.getImportantForAccessibility() == View.IMPORTANT_FOR_ACCESSIBILITY_AUTO) {
|
||||
view.setImportantForAccessibility(View.IMPORTANT_FOR_ACCESSIBILITY_YES);
|
||||
}
|
||||
|
||||
setAccessibilityFocusedHost(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2543,11 +2545,51 @@ public final class ViewRootImpl implements ViewParent,
|
||||
}
|
||||
|
||||
void setAccessibilityFocusedHost(View host) {
|
||||
if (mAccessibilityFocusedHost != null && mAccessibilityFocusedVirtualView == null) {
|
||||
// If we have a virtual view with accessibility focus we need
|
||||
// to clear the focus and invalidate the virtual view bounds.
|
||||
if (mAccessibilityFocusedVirtualView != null) {
|
||||
|
||||
AccessibilityNodeInfo focusNode = mAccessibilityFocusedVirtualView;
|
||||
View focusHost = mAccessibilityFocusedHost;
|
||||
focusHost.clearAccessibilityFocusNoCallbacks();
|
||||
|
||||
// Wipe the state of the current accessibility focus since
|
||||
// the call into the provider to clear accessibility focus
|
||||
// will fire an accessibility event which will end up calling
|
||||
// this method and we want to have clean state when this
|
||||
// invocation happens.
|
||||
mAccessibilityFocusedHost = null;
|
||||
mAccessibilityFocusedVirtualView = null;
|
||||
|
||||
AccessibilityNodeProvider provider = focusHost.getAccessibilityNodeProvider();
|
||||
if (provider != null) {
|
||||
// Invalidate the area of the cleared accessibility focus.
|
||||
focusNode.getBoundsInParent(mTempRect);
|
||||
focusHost.invalidate(mTempRect);
|
||||
// Clear accessibility focus in the virtual node.
|
||||
final int virtualNodeId = AccessibilityNodeInfo.getVirtualDescendantId(
|
||||
focusNode.getSourceNodeId());
|
||||
provider.performAction(virtualNodeId,
|
||||
AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null);
|
||||
}
|
||||
}
|
||||
if (mAccessibilityFocusedHost != null) {
|
||||
// Clear accessibility focus in the view.
|
||||
mAccessibilityFocusedHost.clearAccessibilityFocusNoCallbacks();
|
||||
}
|
||||
|
||||
// Set the new focus host.
|
||||
mAccessibilityFocusedHost = host;
|
||||
mAccessibilityFocusedVirtualView = null;
|
||||
|
||||
// If the host has a provide find the virtual descendant that has focus.
|
||||
if (mAccessibilityFocusedHost != null) {
|
||||
AccessibilityNodeProvider provider =
|
||||
mAccessibilityFocusedHost.getAccessibilityNodeProvider();
|
||||
if (provider != null) {
|
||||
mAccessibilityFocusedVirtualView = provider.findAccessibilityFocus(View.NO_ID);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void requestChildFocus(View child, View focused) {
|
||||
@@ -2633,6 +2675,8 @@ public final class ViewRootImpl implements ViewParent,
|
||||
|
||||
destroyHardwareRenderer();
|
||||
|
||||
setAccessibilityFocusedHost(null);
|
||||
|
||||
mView = null;
|
||||
mAttachInfo.mRootView = null;
|
||||
mAttachInfo.mSurface = null;
|
||||
@@ -4608,6 +4652,31 @@ public final class ViewRootImpl implements ViewParent,
|
||||
if (mView == null) {
|
||||
return false;
|
||||
}
|
||||
// Watch for accessibility focus change events from virtual nodes
|
||||
// to keep track of accessibility focus being on a virtual node.
|
||||
final int eventType = event.getEventType();
|
||||
switch (eventType) {
|
||||
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED: {
|
||||
final long sourceId = event.getSourceNodeId();
|
||||
// If the event is not from a virtual node we are not interested.
|
||||
final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
|
||||
if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
|
||||
break;
|
||||
}
|
||||
final int realViewId = AccessibilityNodeInfo.getAccessibilityViewId(sourceId);
|
||||
View focusHost = mView.findViewByAccessibilityId(realViewId);
|
||||
setAccessibilityFocusedHost(focusHost);
|
||||
} break;
|
||||
case AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED: {
|
||||
final long sourceId = event.getSourceNodeId();
|
||||
// If the event is not from a virtual node we are not interested.
|
||||
final int virtualViewId = AccessibilityNodeInfo.getVirtualDescendantId(sourceId);
|
||||
if (virtualViewId == AccessibilityNodeInfo.UNDEFINED) {
|
||||
break;
|
||||
}
|
||||
setAccessibilityFocusedHost(null);
|
||||
} break;
|
||||
}
|
||||
mAccessibilityManager.sendAccessibilityEvent(event);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -950,6 +950,8 @@ public class NumberPicker extends LinearLayout {
|
||||
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
|
||||
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
|
||||
provider.performAction(hoveredVirtualViewId,
|
||||
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
|
||||
} break;
|
||||
case MotionEvent.ACTION_HOVER_MOVE: {
|
||||
if (mLastHoveredChildVirtualViewId != hoveredVirtualViewId
|
||||
@@ -960,6 +962,8 @@ public class NumberPicker extends LinearLayout {
|
||||
provider.sendAccessibilityEventForVirtualView(hoveredVirtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_HOVER_ENTER);
|
||||
mLastHoveredChildVirtualViewId = hoveredVirtualViewId;
|
||||
provider.performAction(hoveredVirtualViewId,
|
||||
AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS, null);
|
||||
}
|
||||
} break;
|
||||
case MotionEvent.ACTION_HOVER_EXIT: {
|
||||
@@ -1413,9 +1417,16 @@ public class NumberPicker extends LinearLayout {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void sendAccessibilityEvent(int eventType) {
|
||||
// Do not send accessibility events - we want the user to
|
||||
// perceive this widget as several controls rather as a whole.
|
||||
public void addFocusables(ArrayList<View> views, int direction, int focusableMode) {
|
||||
// We do not want the real descendant to be considered focus search
|
||||
// since it is managed by the accessibility node provider.
|
||||
if ((focusableMode & FOCUSABLES_ACCESSIBILITY) == FOCUSABLES_ACCESSIBILITY) {
|
||||
if (canTakeAccessibilityFocusFromHover() || getAccessibilityNodeProvider() != null) {
|
||||
views.add(this);
|
||||
return;
|
||||
}
|
||||
}
|
||||
super.addFocusables(views, direction, focusableMode);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2072,7 +2083,12 @@ public class NumberPicker extends LinearLayout {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Class for managing virtual view tree rooted at this picker.
|
||||
*/
|
||||
class AccessibilityNodeProviderImpl extends AccessibilityNodeProvider {
|
||||
private static final int UNDEFINED = Integer.MIN_VALUE;
|
||||
|
||||
private static final int VIRTUAL_VIEW_ID_INCREMENT = 1;
|
||||
|
||||
private static final int VIRTUAL_VIEW_ID_INPUT = 2;
|
||||
@@ -2083,6 +2099,8 @@ public class NumberPicker extends LinearLayout {
|
||||
|
||||
private final int[] mTempArray = new int[2];
|
||||
|
||||
private int mAccessibilityFocusedView = UNDEFINED;
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo createAccessibilityNodeInfo(int virtualViewId) {
|
||||
switch (virtualViewId) {
|
||||
@@ -2137,6 +2155,25 @@ public class NumberPicker extends LinearLayout {
|
||||
@Override
|
||||
public boolean performAction(int virtualViewId, int action, Bundle arguments) {
|
||||
switch (virtualViewId) {
|
||||
case View.NO_ID: {
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView != virtualViewId) {
|
||||
mAccessibilityFocusedView = virtualViewId;
|
||||
requestAccessibilityFocus();
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView == virtualViewId) {
|
||||
mAccessibilityFocusedView = UNDEFINED;
|
||||
clearAccessibilityFocus();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case VIRTUAL_VIEW_ID_INPUT: {
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_FOCUS: {
|
||||
@@ -2149,25 +2186,182 @@ public class NumberPicker extends LinearLayout {
|
||||
mInputText.clearFocus();
|
||||
return true;
|
||||
}
|
||||
} break;
|
||||
return false;
|
||||
}
|
||||
case AccessibilityNodeInfo.ACTION_CLICK: {
|
||||
showSoftInput();
|
||||
return true;
|
||||
}
|
||||
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView != virtualViewId) {
|
||||
mAccessibilityFocusedView = virtualViewId;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
mInputText.invalidate();
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView == virtualViewId) {
|
||||
mAccessibilityFocusedView = UNDEFINED;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||
mInputText.invalidate();
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
default: {
|
||||
return mInputText.performAccessibilityAction(action, arguments);
|
||||
}
|
||||
}
|
||||
} return false;
|
||||
case VIRTUAL_VIEW_ID_INCREMENT: {
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_CLICK: {
|
||||
NumberPicker.this.changeValueByOne(true);
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
} return true;
|
||||
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView != virtualViewId) {
|
||||
mAccessibilityFocusedView = virtualViewId;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView == virtualViewId) {
|
||||
mAccessibilityFocusedView = UNDEFINED;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||
invalidate(0, mBottomSelectionDividerBottom, mRight, mBottom);
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
}
|
||||
} return false;
|
||||
case VIRTUAL_VIEW_ID_DECREMENT: {
|
||||
switch (action) {
|
||||
case AccessibilityNodeInfo.ACTION_CLICK: {
|
||||
final boolean increment = (virtualViewId == VIRTUAL_VIEW_ID_INCREMENT);
|
||||
NumberPicker.this.changeValueByOne(increment);
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_CLICKED);
|
||||
} return true;
|
||||
case AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView != virtualViewId) {
|
||||
mAccessibilityFocusedView = virtualViewId;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED);
|
||||
invalidate(0, 0, mRight, mTopSelectionDividerTop);
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
case AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS: {
|
||||
if (mAccessibilityFocusedView == virtualViewId) {
|
||||
mAccessibilityFocusedView = UNDEFINED;
|
||||
sendAccessibilityEventForVirtualView(virtualViewId,
|
||||
AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED);
|
||||
invalidate(0, 0, mRight, mTopSelectionDividerTop);
|
||||
return true;
|
||||
}
|
||||
} return false;
|
||||
}
|
||||
} return false;
|
||||
}
|
||||
return super.performAction(virtualViewId, action, arguments);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo findAccessibilityFocus(int virtualViewId) {
|
||||
return createAccessibilityNodeInfo(mAccessibilityFocusedView);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AccessibilityNodeInfo accessibilityFocusSearch(int direction, int virtualViewId) {
|
||||
switch (direction) {
|
||||
case View.ACCESSIBILITY_FOCUS_DOWN:
|
||||
case View.ACCESSIBILITY_FOCUS_FORWARD: {
|
||||
switch (mAccessibilityFocusedView) {
|
||||
case UNDEFINED: {
|
||||
return createAccessibilityNodeInfo(View.NO_ID);
|
||||
}
|
||||
case View.NO_ID: {
|
||||
if (hasVirtualDecrementButton()) {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
|
||||
}
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
case VIRTUAL_VIEW_ID_DECREMENT: {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
|
||||
}
|
||||
case VIRTUAL_VIEW_ID_INPUT: {
|
||||
if (hasVirtualIncrementButton()) {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
|
||||
}
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
case VIRTUAL_VIEW_ID_INCREMENT: {
|
||||
View nextFocus = NumberPicker.this.focusSearch(direction);
|
||||
if (nextFocus != null) {
|
||||
return nextFocus.createAccessibilityNodeInfo();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
case View.ACCESSIBILITY_FOCUS_UP:
|
||||
case View.ACCESSIBILITY_FOCUS_BACKWARD: {
|
||||
switch (mAccessibilityFocusedView) {
|
||||
case UNDEFINED: {
|
||||
return createAccessibilityNodeInfo(View.NO_ID);
|
||||
}
|
||||
case View.NO_ID: {
|
||||
if (hasVirtualIncrementButton()) {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INCREMENT);
|
||||
}
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
case VIRTUAL_VIEW_ID_INCREMENT: {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_INPUT);
|
||||
}
|
||||
case VIRTUAL_VIEW_ID_INPUT: {
|
||||
if (hasVirtualDecrementButton()) {
|
||||
return createAccessibilityNodeInfo(VIRTUAL_VIEW_ID_DECREMENT);
|
||||
}
|
||||
}
|
||||
//$FALL-THROUGH$
|
||||
case VIRTUAL_VIEW_ID_DECREMENT: {
|
||||
View nextFocus = NumberPicker.this.focusSearch(direction);
|
||||
if (nextFocus != null) {
|
||||
return nextFocus.createAccessibilityNodeInfo();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} break;
|
||||
}
|
||||
return super.performAction(virtualViewId, action, arguments);
|
||||
return null;
|
||||
}
|
||||
|
||||
public void sendAccessibilityEventForVirtualView(int virtualViewId, int eventType) {
|
||||
switch (virtualViewId) {
|
||||
case VIRTUAL_VIEW_ID_DECREMENT: {
|
||||
sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
|
||||
getVirtualDecrementButtonText());
|
||||
if (hasVirtualDecrementButton()) {
|
||||
sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
|
||||
getVirtualDecrementButtonText());
|
||||
}
|
||||
} break;
|
||||
case VIRTUAL_VIEW_ID_INPUT: {
|
||||
sendAccessibilityEventForVirtualText(eventType);
|
||||
} break;
|
||||
case VIRTUAL_VIEW_ID_INCREMENT: {
|
||||
sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
|
||||
getVirtualIncrementButtonText());
|
||||
if (hasVirtualIncrementButton()) {
|
||||
sendAccessibilityEventForVirtualButton(virtualViewId, eventType,
|
||||
getVirtualIncrementButtonText());
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
@@ -2227,8 +2421,13 @@ public class NumberPicker extends LinearLayout {
|
||||
|
||||
private AccessibilityNodeInfo createAccessibiltyNodeInfoForInputText() {
|
||||
AccessibilityNodeInfo info = mInputText.createAccessibilityNodeInfo();
|
||||
info.setLongClickable(true);
|
||||
info.setSource(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
|
||||
if (mAccessibilityFocusedView != VIRTUAL_VIEW_ID_INPUT) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
if (mAccessibilityFocusedView == VIRTUAL_VIEW_ID_INPUT) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -2252,6 +2451,15 @@ public class NumberPicker extends LinearLayout {
|
||||
getLocationOnScreen(locationOnScreen);
|
||||
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
|
||||
info.setBoundsInScreen(boundsInScreen);
|
||||
|
||||
if (mAccessibilityFocusedView != virtualViewId) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
if (mAccessibilityFocusedView == virtualViewId) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLICK);
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
@@ -2261,9 +2469,15 @@ public class NumberPicker extends LinearLayout {
|
||||
info.setClassName(NumberPicker.class.getName());
|
||||
info.setPackageName(mContext.getPackageName());
|
||||
info.setSource(NumberPicker.this);
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
|
||||
|
||||
if (hasVirtualDecrementButton()) {
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_DECREMENT);
|
||||
}
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INPUT);
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
|
||||
if (hasVirtualIncrementButton()) {
|
||||
info.addChild(NumberPicker.this, VIRTUAL_VIEW_ID_INCREMENT);
|
||||
}
|
||||
|
||||
info.setParent((View) getParent());
|
||||
info.setEnabled(NumberPicker.this.isEnabled());
|
||||
info.setScrollable(true);
|
||||
@@ -2276,9 +2490,25 @@ public class NumberPicker extends LinearLayout {
|
||||
getLocationOnScreen(locationOnScreen);
|
||||
boundsInScreen.offset(locationOnScreen[0], locationOnScreen[1]);
|
||||
info.setBoundsInScreen(boundsInScreen);
|
||||
|
||||
if (mAccessibilityFocusedView != View.NO_ID) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
if (mAccessibilityFocusedView == View.NO_ID) {
|
||||
info.addAction(AccessibilityNodeInfo.ACTION_CLEAR_ACCESSIBILITY_FOCUS);
|
||||
}
|
||||
|
||||
return info;
|
||||
}
|
||||
|
||||
private boolean hasVirtualDecrementButton() {
|
||||
return getWrapSelectorWheel() || getValue() > getMinValue();
|
||||
}
|
||||
|
||||
private boolean hasVirtualIncrementButton() {
|
||||
return getWrapSelectorWheel() || getValue() < getMaxValue();
|
||||
}
|
||||
|
||||
private String getVirtualDecrementButtonText() {
|
||||
int value = mValue - 1;
|
||||
if (mWrapSelectorWheel) {
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center_vertical"
|
||||
android:importantForAccessibility="no"
|
||||
/>
|
||||
|
||||
<!-- minute -->
|
||||
|
||||
Reference in New Issue
Block a user