diff options
| author | TreeHugger Robot <treehugger-gerrit@google.com> | 2018-01-25 05:20:46 +0000 |
|---|---|---|
| committer | Android (Google) Code Review <android-gerrit@google.com> | 2018-01-25 05:20:46 +0000 |
| commit | 224484aaf948a086a8d6ccbbbb14e52d7263ed85 (patch) | |
| tree | 8e078af366822366958315e63a9b571ba8576020 /core/java | |
| parent | 3613d936a98ccd8ae98b83185f4a6b5931a0f126 (diff) | |
| parent | d89905f0a46dea3d8ca8d0bacc0c33db488e0b36 (diff) | |
Merge "Re-commit: Add accessibility support for tooltips"
Diffstat (limited to 'core/java')
| -rw-r--r-- | core/java/android/view/View.java | 60 | ||||
| -rw-r--r-- | core/java/android/view/accessibility/AccessibilityNodeInfo.java | 56 |
2 files changed, 95 insertions, 21 deletions
diff --git a/core/java/android/view/View.java b/core/java/android/view/View.java index b0ea3f167608..3d6a6fee081b 100644 --- a/core/java/android/view/View.java +++ b/core/java/android/view/View.java @@ -16,6 +16,8 @@ package android.view; +import static android.view.accessibility.AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED; + import static java.lang.Math.max; import android.animation.AnimatorInflater; @@ -8548,6 +8550,12 @@ public class View implements Drawable.Callback, KeyEvent.Callback, info.setLongClickable(isLongClickable()); info.setContextClickable(isContextClickable()); info.setLiveRegion(getAccessibilityLiveRegion()); + if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipText != null)) { + info.setTooltipText(mTooltipInfo.mTooltipText); + info.addAction((mTooltipInfo.mTooltipPopup == null) + ? AccessibilityNodeInfo.AccessibilityAction.ACTION_SHOW_TOOLTIP + : AccessibilityNodeInfo.AccessibilityAction.ACTION_HIDE_TOOLTIP); + } // TODO: These make sense only if we are in an AdapterView but all // views can be selected. Maybe from accessibility perspective @@ -8951,8 +8959,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } mAccessibilityTraversalBeforeId = beforeId; - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } /** @@ -8995,8 +9002,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return; } mAccessibilityTraversalAfterId = afterId; - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } /** @@ -9038,8 +9044,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, && mID == View.NO_ID) { mID = generateViewId(); } - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } /** @@ -10539,7 +10544,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (pflags3 != mPrivateFlags3) { mPrivateFlags3 = pflags3; - notifyAccessibilityStateChanged(AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } @@ -11369,8 +11374,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, mPrivateFlags2 &= ~PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; mPrivateFlags2 |= (mode << PFLAG2_ACCESSIBILITY_LIVE_REGION_SHIFT) & PFLAG2_ACCESSIBILITY_LIVE_REGION_MASK; - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } @@ -11429,8 +11433,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (!maySkipNotify || oldIncludeForAccessibility != includeForAccessibility()) { notifyAccessibilitySubtreeChanged(); } else { - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } } @@ -11840,8 +11843,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, || getAccessibilitySelectionEnd() != end) && (start == end)) { setAccessibilitySelection(start, end); - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); return true; } } break; @@ -11858,6 +11860,21 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return true; } } break; + case R.id.accessibilityActionShowTooltip: { + if ((mTooltipInfo != null) && (mTooltipInfo.mTooltipPopup != null)) { + // Tooltip already showing + return false; + } + return showLongClickTooltip(0, 0); + } + case R.id.accessibilityActionHideTooltip: { + if ((mTooltipInfo == null) || (mTooltipInfo.mTooltipPopup == null)) { + // No tooltip showing + return false; + } + hideTooltip(); + return true; + } } return false; } @@ -13891,12 +13908,10 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (oldIncludeForAccessibility != includeForAccessibility()) { notifyAccessibilitySubtreeChanged(); } else { - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } else if ((changed & ENABLED_MASK) != 0) { - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } } @@ -21856,8 +21871,7 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (selected) { sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_SELECTED); } else { - notifyAccessibilityStateChanged( - AccessibilityEvent.CONTENT_CHANGE_TYPE_UNDEFINED); + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } } } @@ -27059,6 +27073,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, final boolean fromTouch = (mPrivateFlags3 & PFLAG3_FINGER_DOWN) == PFLAG3_FINGER_DOWN; mTooltipInfo.mTooltipPopup.show(this, x, y, fromTouch, mTooltipInfo.mTooltipText); mAttachInfo.mTooltipHost = this; + // The available accessibility actions have changed + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); return true; } @@ -27077,6 +27093,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, if (mAttachInfo != null) { mAttachInfo.mTooltipHost = null; } + // The available accessibility actions have changed + notifyAccessibilityStateChanged(CONTENT_CHANGE_TYPE_UNDEFINED); } private boolean showLongClickTooltip(int x, int y) { @@ -27085,8 +27103,8 @@ public class View implements Drawable.Callback, KeyEvent.Callback, return showTooltip(x, y, true); } - private void showHoverTooltip() { - showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false); + private boolean showHoverTooltip() { + return showTooltip(mTooltipInfo.mAnchorX, mTooltipInfo.mAnchorY, false); } boolean dispatchTooltipHoverEvent(MotionEvent event) { diff --git a/core/java/android/view/accessibility/AccessibilityNodeInfo.java b/core/java/android/view/accessibility/AccessibilityNodeInfo.java index 3ee282ec3ac2..23e7d6191276 100644 --- a/core/java/android/view/accessibility/AccessibilityNodeInfo.java +++ b/core/java/android/view/accessibility/AccessibilityNodeInfo.java @@ -727,6 +727,7 @@ public class AccessibilityNodeInfo implements Parcelable { private CharSequence mError; private CharSequence mPaneTitle; private CharSequence mContentDescription; + private CharSequence mTooltipText; private String mViewIdResourceName; private ArrayList<String> mExtraDataKeys; @@ -2655,6 +2656,34 @@ public class AccessibilityNodeInfo implements Parcelable { } /** + * Gets the tooltip text of this node. + * + * @return The tooltip text. + */ + @Nullable + public CharSequence getTooltipText() { + return mTooltipText; + } + + /** + * Sets the tooltip text of 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 tooltipText The tooltip text. + * + * @throws IllegalStateException If called from an AccessibilityService. + */ + public void setTooltipText(@Nullable CharSequence tooltipText) { + enforceNotSealed(); + mTooltipText = (tooltipText == null) ? null + : tooltipText.subSequence(0, tooltipText.length()); + } + + /** * Sets the view for which the view represented by this info serves as a * label for accessibility purposes. * @@ -3209,6 +3238,10 @@ public class AccessibilityNodeInfo implements Parcelable { nonDefaultFields |= bitAt(fieldIndex); } fieldIndex++; + if (!Objects.equals(mTooltipText, DEFAULT.mTooltipText)) { + nonDefaultFields |= bitAt(fieldIndex); + } + fieldIndex++; if (!Objects.equals(mViewIdResourceName, DEFAULT.mViewIdResourceName)) { nonDefaultFields |= bitAt(fieldIndex); } @@ -3329,6 +3362,8 @@ public class AccessibilityNodeInfo implements Parcelable { parcel.writeCharSequence(mContentDescription); } if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mPaneTitle); + if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeCharSequence(mTooltipText); + if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeString(mViewIdResourceName); if (isBitSet(nonDefaultFields, fieldIndex++)) parcel.writeInt(mTextSelectionStart); @@ -3401,6 +3436,7 @@ public class AccessibilityNodeInfo implements Parcelable { mError = other.mError; mContentDescription = other.mContentDescription; mPaneTitle = other.mPaneTitle; + mTooltipText = other.mTooltipText; mViewIdResourceName = other.mViewIdResourceName; if (mActions != null) mActions.clear(); @@ -3522,6 +3558,7 @@ public class AccessibilityNodeInfo implements Parcelable { mContentDescription = parcel.readCharSequence(); } if (isBitSet(nonDefaultFields, fieldIndex++)) mPaneTitle = parcel.readString(); + if (isBitSet(nonDefaultFields, fieldIndex++)) mTooltipText = parcel.readCharSequence(); if (isBitSet(nonDefaultFields, fieldIndex++)) mViewIdResourceName = parcel.readString(); if (isBitSet(nonDefaultFields, fieldIndex++)) mTextSelectionStart = parcel.readInt(); @@ -3684,6 +3721,10 @@ public class AccessibilityNodeInfo implements Parcelable { return "ACTION_SET_PROGRESS"; case R.id.accessibilityActionContextClick: return "ACTION_CONTEXT_CLICK"; + case R.id.accessibilityActionShowTooltip: + return "ACTION_SHOW_TOOLTIP"; + case R.id.accessibilityActionHideTooltip: + return "ACTION_HIDE_TOOLTIP"; default: return "ACTION_UNKNOWN"; } @@ -3797,6 +3838,7 @@ public class AccessibilityNodeInfo implements Parcelable { builder.append("; error: ").append(mError); builder.append("; maxTextLength: ").append(mMaxTextLength); builder.append("; contentDescription: ").append(mContentDescription); + builder.append("; tooltipText: ").append(mTooltipText); builder.append("; viewIdResName: ").append(mViewIdResourceName); builder.append("; checkable: ").append(isCheckable()); @@ -4211,6 +4253,20 @@ public class AccessibilityNodeInfo implements Parcelable { public static final AccessibilityAction ACTION_MOVE_WINDOW = new AccessibilityAction(R.id.accessibilityActionMoveWindow); + /** + * Action to show a tooltip. A node should expose this action only for views with tooltip + * text that but are not currently showing a tooltip. + */ + public static final AccessibilityAction ACTION_SHOW_TOOLTIP = + new AccessibilityAction(R.id.accessibilityActionShowTooltip); + + /** + * Action to hide a tooltip. A node should expose this action only for views that are + * currently showing a tooltip. + */ + public static final AccessibilityAction ACTION_HIDE_TOOLTIP = + new AccessibilityAction(R.id.accessibilityActionHideTooltip); + private final int mActionId; private final CharSequence mLabel; |
