diff options
author | Alan Viverette <alanv@google.com> | 2013-05-30 16:10:05 -0700 |
---|---|---|
committer | Alan Viverette <alanv@google.com> | 2013-05-30 16:10:05 -0700 |
commit | 2994491d65ecb60debc2671535516d3225261049 (patch) | |
tree | ef4e1dd5a7790c7e313f424bfe7698d93642df88 | |
parent | d461f9bf70f3763e005275ef8707b1fd41e9293a (diff) | |
download | android_frameworks_opt_datetimepicker-2994491d65ecb60debc2671535516d3225261049.tar.gz android_frameworks_opt_datetimepicker-2994491d65ecb60debc2671535516d3225261049.tar.bz2 android_frameworks_opt_datetimepicker-2994491d65ecb60debc2671535516d3225261049.zip |
Switch calendar accessibility to use new ExploreByTouchHelper.
Change-Id: Idc2e268cdaa68524f7a5e7abf7276d8afec8dbba
-rw-r--r-- | src/com/android/datetimepicker/date/SimpleMonthView.java | 166 | ||||
-rw-r--r-- | src/com/googlecode/eyesfree/utils/TouchExplorationHelper.java | 475 |
2 files changed, 73 insertions, 568 deletions
diff --git a/src/com/android/datetimepicker/date/SimpleMonthView.java b/src/com/android/datetimepicker/date/SimpleMonthView.java index 832bdfb..9d88117 100644 --- a/src/com/android/datetimepicker/date/SimpleMonthView.java +++ b/src/com/android/datetimepicker/date/SimpleMonthView.java @@ -27,10 +27,10 @@ import android.graphics.Typeface; import android.os.Bundle; import android.support.v4.view.ViewCompat; import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; +import android.support.v4.widget.ExploreByTouchHelper; import android.text.format.DateFormat; import android.text.format.DateUtils; import android.text.format.Time; -import android.util.SparseArray; import android.view.MotionEvent; import android.view.View; import android.view.accessibility.AccessibilityEvent; @@ -39,7 +39,6 @@ import android.view.accessibility.AccessibilityNodeInfo; import com.android.datetimepicker.R; import com.android.datetimepicker.Utils; import com.android.datetimepicker.date.SimpleMonthAdapter.CalendarDay; -import com.googlecode.eyesfree.utils.TouchExplorationHelper; import java.security.InvalidParameterException; import java.util.Calendar; @@ -169,7 +168,7 @@ public class SimpleMonthView extends View { private final Calendar mCalendar; private final Calendar mDayLabelCalendar; - private final MonthViewNodeProvider mNodeProvider; + private final MonthViewTouchHelper mTouchHelper; private int mNumRows = DEFAULT_NUM_ROWS; @@ -213,8 +212,8 @@ public class SimpleMonthView extends View { - MONTH_HEADER_SIZE) / MAX_NUM_ROWS; // Set up accessibility components. - mNodeProvider = new MonthViewNodeProvider(context, this); - ViewCompat.setAccessibilityDelegate(this, mNodeProvider.getAccessibilityDelegate()); + mTouchHelper = new MonthViewTouchHelper(this); + ViewCompat.setAccessibilityDelegate(this, mTouchHelper); ViewCompat.setImportantForAccessibility(this, ViewCompat.IMPORTANT_FOR_ACCESSIBILITY_YES); mLockAccessibilityDelegate = true; @@ -236,20 +235,20 @@ public class SimpleMonthView extends View { } @Override - public boolean onHoverEvent(MotionEvent event) { + public boolean dispatchHoverEvent(MotionEvent event) { // First right-of-refusal goes the touch exploration helper. - if (mNodeProvider.onHover(this, event)) { + if (mTouchHelper.dispatchHoverEvent(event)) { return true; } - return super.onHoverEvent(event); + return super.dispatchHoverEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_UP: - final CalendarDay day = getDayFromLocation(event.getX(), event.getY()); - if (day != null) { + final int day = getDayFromLocation(event.getX(), event.getY()); + if (day >= 0) { onDayClick(day); } break; @@ -321,7 +320,6 @@ public class SimpleMonthView extends View { * * @param params A map of the new parameters, see * {@link #VIEW_PARAMS_HEIGHT} - * @param tz The time zone this view should reference times in */ public void setMonthParams(HashMap<String, Integer> params) { if (!params.containsKey(VIEW_PARAMS_MONTH) && !params.containsKey(VIEW_PARAMS_YEAR)) { @@ -371,7 +369,7 @@ public class SimpleMonthView extends View { mNumRows = calculateNumRows(); // Invalidate cached accessibility information. - mNodeProvider.invalidateParent(); + mTouchHelper.invalidateRoot(); } public void reuse() { @@ -403,7 +401,7 @@ public class SimpleMonthView extends View { mWidth = w; // Invalidate cached accessibility information. - mNodeProvider.invalidateParent(); + mTouchHelper.invalidateRoot(); } private String getMonthAndYearString() { @@ -475,16 +473,15 @@ public class SimpleMonthView extends View { /** * Calculates the day that the given x position is in, accounting for week - * number. Returns a Time referencing that day or null if + * number. Returns the day or -1 if the position wasn't in a day. * * @param x The x position of the touch event - * @return A time object for the tapped day or null if the position wasn't - * in a day + * @return The day number, or -1 if the position wasn't in a day */ - public CalendarDay getDayFromLocation(float x, float y) { + public int getDayFromLocation(float x, float y) { int dayStart = mPadding; if (x < dayStart || x > mWidth - mPadding) { - return null; + return -1; } // Selection is (x - start) / (pixels/day) == (x -s) * day / pixels int row = (int) (y - MONTH_HEADER_SIZE) / mRowHeight; @@ -493,24 +490,24 @@ public class SimpleMonthView extends View { int day = column - findDayOffset() + 1; day += row * mNumDays; if (day < 1 || day > mNumCells) { - return null; + return -1; } - return new CalendarDay(mYear, mMonth, day); + return day; } /** * Called when the user clicks on a day. Handles callbacks to the * {@link OnDayClickListener} if one is set. * - * @param day A time object representing the day that was clicked + * @param day The day that was clicked */ - private void onDayClick(CalendarDay day) { + private void onDayClick(int day) { if (mOnDayClickListener != null) { - mOnDayClickListener.onDayClick(this, day); + mOnDayClickListener.onDayClick(this, new CalendarDay(mYear, mMonth, day)); } // This is a no-op if accessibility is turned off. - mNodeProvider.sendEventForItem(day, AccessibilityEvent.TYPE_VIEW_CLICKED); + mTouchHelper.sendEventForVirtualView(day, AccessibilityEvent.TYPE_VIEW_CLICKED); } /** @@ -518,7 +515,11 @@ public class SimpleMonthView extends View { * has focus */ public CalendarDay getAccessibilityFocus() { - return mNodeProvider.getFocusedItem(); + final int day = mTouchHelper.getFocusedVirtualView(); + if (day >= 0) { + return new CalendarDay(mYear, mMonth, day); + } + return null; } /** @@ -526,7 +527,7 @@ public class SimpleMonthView extends View { * contain accessibility focus. */ public void clearAccessibilityFocus() { - mNodeProvider.clearFocusedItem(); + mTouchHelper.clearFocusedVirtualView(); } /** @@ -540,8 +541,7 @@ public class SimpleMonthView extends View { if ((day.year != mYear) || (day.month != mMonth) || (day.day > mNumCells)) { return false; } - - mNodeProvider.setFocusedItem(day); + mTouchHelper.setFocusedVirtualView(day.day); return true; } @@ -549,104 +549,87 @@ public class SimpleMonthView extends View { * Provides a virtual view hierarchy for interfacing with an accessibility * service. */ - private class MonthViewNodeProvider extends TouchExplorationHelper<CalendarDay> { - private final SparseArray<CalendarDay> mCachedItems = new SparseArray<CalendarDay>(); + private class MonthViewTouchHelper extends ExploreByTouchHelper { + private static final String DATE_FORMAT = "dd MMMM yyyy"; + private final Rect mTempRect = new Rect(); + private final Calendar mTempCalendar = Calendar.getInstance(); - Calendar recycle; + public MonthViewTouchHelper(View host) { + super(host); + } - public MonthViewNodeProvider(Context context, View parent) { - super(context, parent); + public void setFocusedVirtualView(int virtualViewId) { + getAccessibilityNodeProvider(SimpleMonthView.this).performAction( + virtualViewId, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null); } - @Override - public void invalidateItem(CalendarDay item) { - super.invalidateItem(item); - mCachedItems.delete(getIdForItem(item)); + public void clearFocusedVirtualView() { + final int focusedVirtualView = getFocusedVirtualView(); + if (focusedVirtualView != ExploreByTouchHelper.INVALID_ID) { + getAccessibilityNodeProvider(SimpleMonthView.this).performAction( + focusedVirtualView, AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); + } } @Override - public void invalidateParent() { - super.invalidateParent(); - mCachedItems.clear(); + protected int getVirtualViewAt(float x, float y) { + final int day = getDayFromLocation(x, y); + if (day >= 0) { + return day; + } + return ExploreByTouchHelper.INVALID_ID; } @Override - protected boolean performActionForItem(CalendarDay item, int action, Bundle arguments) { - switch (action) { - case AccessibilityNodeInfo.ACTION_CLICK: - onDayClick(item); - return true; + protected void getVisibleVirtualViews(List<Integer> virtualViewIds) { + for (int day = 1; day <= mNumCells; day++) { + virtualViewIds.add(day); } - - return false; } @Override - protected void populateEventForItem(CalendarDay item, AccessibilityEvent event) { - event.setContentDescription(getItemDescription(item)); + protected void onPopulateEventForVirtualView(int virtualViewId, AccessibilityEvent event) { + event.setContentDescription(getItemDescription(virtualViewId)); } @Override - protected void populateNodeForItem(CalendarDay item, AccessibilityNodeInfoCompat node) { - getItemBounds(item, mTempRect); + protected void onPopulateNodeForVirtualView(int virtualViewId, AccessibilityNodeInfoCompat node) { + getItemBounds(virtualViewId, mTempRect); - node.setContentDescription(getItemDescription(item)); + node.setContentDescription(getItemDescription(virtualViewId)); node.setBoundsInParent(mTempRect); node.addAction(AccessibilityNodeInfo.ACTION_CLICK); - if (item.day == mSelectedDay) { + if (virtualViewId == mSelectedDay) { node.setSelected(true); } - } - @Override - protected void getVisibleItems(List<CalendarDay> items) { - // TODO: Optimize, only return items visible within parent bounds. - for (int day = 1; day <= mNumCells; day++) { - items.add(getItemForId(day)); - } - } - - @Override - protected CalendarDay getItemAt(float x, float y) { - return getDayFromLocation(x, y); } @Override - protected int getIdForItem(CalendarDay item) { - return item.day; - } - - @Override - protected CalendarDay getItemForId(int id) { - if ((id < 1) || (id > mNumCells)) { - return null; - } - - final CalendarDay item; - if (mCachedItems.indexOfKey(id) >= 0) { - item = mCachedItems.get(id); - } else { - item = new CalendarDay(mYear, mMonth, id); - mCachedItems.put(id, item); + protected boolean onPerformActionForVirtualView(int virtualViewId, int action, Bundle arguments) { + switch (action) { + case AccessibilityNodeInfo.ACTION_CLICK: + onDayClick(virtualViewId); + return true; } - return item; + return false; } /** * Calculates the bounding rectangle of a given time object. * - * @param item The time object to calculate bounds for + * @param day The day to calculate bounds for * @param rect The rectangle in which to store the bounds */ - private void getItemBounds(CalendarDay item, Rect rect) { + private void getItemBounds(int day, Rect rect) { final int offsetX = mPadding; final int offsetY = MONTH_HEADER_SIZE; final int cellHeight = mRowHeight; final int cellWidth = ((mWidth - (2 * mPadding)) / mNumDays); - final int index = ((item.day - 1) + findDayOffset()); + final int index = ((day - 1) + findDayOffset()); final int row = (index / mNumDays); final int column = (index % mNumDays); final int x = (offsetX + (column * cellWidth)); @@ -660,17 +643,14 @@ public class SimpleMonthView extends View { * description will be spoken, the components are ordered by descending * specificity as DAY MONTH YEAR. * - * @param item The time object to generate a description for + * @param day The day to generate a description for * @return A description of the time object */ - private CharSequence getItemDescription(CalendarDay item) { - if (recycle == null) { - recycle = Calendar.getInstance(); - } - recycle.set(item.year, item.month, item.day); - CharSequence date = DateFormat.format("dd MMMM yyyy", recycle.getTimeInMillis()); + private CharSequence getItemDescription(int day) { + mTempCalendar.set(mYear, mMonth, day); + final CharSequence date = DateFormat.format(DATE_FORMAT, mTempCalendar.getTimeInMillis()); - if (item.day == mSelectedDay) { + if (day == mSelectedDay) { return getContext().getString(R.string.item_is_selected, date); } diff --git a/src/com/googlecode/eyesfree/utils/TouchExplorationHelper.java b/src/com/googlecode/eyesfree/utils/TouchExplorationHelper.java deleted file mode 100644 index b9df653..0000000 --- a/src/com/googlecode/eyesfree/utils/TouchExplorationHelper.java +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2012 Google Inc. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not - * use this file except in compliance with the License. You may obtain a copy of - * the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the - * License for the specific language governing permissions and limitations under - * the License. - */ - -package com.googlecode.eyesfree.utils; - -import android.content.Context; -import android.graphics.Rect; -import android.os.Bundle; -import android.support.v4.view.AccessibilityDelegateCompat; -import android.support.v4.view.ViewCompat; -import android.support.v4.view.accessibility.AccessibilityNodeInfoCompat; -import android.support.v4.view.accessibility.AccessibilityNodeProviderCompat; -import android.support.v4.view.accessibility.AccessibilityRecordCompat; -import android.text.TextUtils; -import android.view.MotionEvent; -import android.view.View; -import android.view.ViewGroup; -import android.view.accessibility.AccessibilityEvent; -import android.view.accessibility.AccessibilityManager; - -import java.util.LinkedList; -import java.util.List; - -public abstract class TouchExplorationHelper<T> extends AccessibilityNodeProviderCompat - implements View.OnHoverListener { - /** Virtual node identifier value for invalid nodes. */ - public static final int INVALID_ID = Integer.MIN_VALUE; - - private final Rect mTempScreenRect = new Rect(); - private final Rect mTempParentRect = new Rect(); - private final Rect mTempVisibleRect = new Rect(); - private final int[] mTempGlobalRect = new int[2]; - - private final AccessibilityManager mManager; - - private View mParentView; - private int mFocusedItemId = INVALID_ID; - private T mCurrentItem = null; - - /** - * Constructs a new touch exploration helper. - * - * @param context The parent context. - */ - public TouchExplorationHelper(Context context, View parentView) { - mManager = (AccessibilityManager) context.getSystemService(Context.ACCESSIBILITY_SERVICE); - mParentView = parentView; - } - - /** - * @return The current accessibility focused item, or {@code null} if no - * item is focused. - */ - public T getFocusedItem() { - return getItemForId(mFocusedItemId); - } - - /** - * Clears the current accessibility focused item. - */ - public void clearFocusedItem() { - final int itemId = mFocusedItemId; - if (itemId == INVALID_ID) { - return; - } - - performAction(itemId, AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS, null); - } - - /** - * Requests accessibility focus be placed on the specified item. - * - * @param item The item to place focus on. - */ - public void setFocusedItem(T item) { - final int itemId = getIdForItem(item); - if (itemId == INVALID_ID) { - return; - } - - performAction(itemId, AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS, null); - } - - /** - * Invalidates cached information about the parent view. - * <p> - * You <b>must</b> call this method after adding or removing items from the - * parent view. - * </p> - */ - public void invalidateParent() { - mParentView.sendAccessibilityEvent(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - } - - /** - * Invalidates cached information for a particular item. - * <p> - * You <b>must</b> call this method when any of the properties set in - * {@link #populateNodeForItem(Object, AccessibilityNodeInfoCompat)} have - * changed. - * </p> - * - * @param item - */ - public void invalidateItem(T item) { - sendEventForItem(item, AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED); - } - - /** - * Populates an event of the specified type with information about an item - * and attempts to send it up through the view hierarchy. - * - * @param item The item for which to send an event. - * @param eventType The type of event to send. - * @return {@code true} if the event was sent successfully. - */ - public boolean sendEventForItem(T item, int eventType) { - if (!mManager.isEnabled()) { - return false; - } - - final AccessibilityEvent event = getEventForItem(item, eventType); - final ViewGroup group = (ViewGroup) mParentView.getParent(); - - return group.requestSendAccessibilityEvent(mParentView, event); - } - - @Override - public AccessibilityNodeInfoCompat createAccessibilityNodeInfo(int virtualViewId) { - if (virtualViewId == View.NO_ID) { - return getNodeForParent(); - } - - final T item = getItemForId(virtualViewId); - if (item == null) { - return null; - } - - final AccessibilityNodeInfoCompat node = AccessibilityNodeInfoCompat.obtain(); - populateNodeForItemInternal(item, node); - return node; - } - - @Override - public boolean performAction(int virtualViewId, int action, Bundle arguments) { - if (virtualViewId == View.NO_ID) { - return ViewCompat.performAccessibilityAction(mParentView, action, arguments); - } - - final T item = getItemForId(virtualViewId); - if (item == null) { - return false; - } - - boolean handled = false; - - switch (action) { - case AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS: - if (mFocusedItemId != virtualViewId) { - mFocusedItemId = virtualViewId; - sendEventForItem(item, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUSED); - handled = true; - } - break; - case AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS: - if (mFocusedItemId == virtualViewId) { - mFocusedItemId = INVALID_ID; - sendEventForItem(item, AccessibilityEvent.TYPE_VIEW_ACCESSIBILITY_FOCUS_CLEARED); - handled = true; - } - break; - } - - handled |= performActionForItem(item, action, arguments); - - return handled; - } - - @Override - public boolean onHover(View view, MotionEvent event) { - if (!mManager.isTouchExplorationEnabled()) { - return false; - } - - switch (event.getAction()) { - case MotionEvent.ACTION_HOVER_ENTER: - case MotionEvent.ACTION_HOVER_MOVE: - final T item = getItemAt(event.getX(), event.getY()); - setCurrentItem(item); - return true; - case MotionEvent.ACTION_HOVER_EXIT: - setCurrentItem(null); - return true; - } - - return false; - } - - private void setCurrentItem(T item) { - if (mCurrentItem == item) { - return; - } - - if (mCurrentItem != null) { - sendEventForItem(mCurrentItem, AccessibilityEvent.TYPE_VIEW_HOVER_EXIT); - } - - mCurrentItem = item; - - if (mCurrentItem != null) { - sendEventForItem(mCurrentItem, AccessibilityEvent.TYPE_VIEW_HOVER_ENTER); - } - } - - private AccessibilityEvent getEventForItem(T item, int eventType) { - final AccessibilityEvent event = AccessibilityEvent.obtain(eventType); - final AccessibilityRecordCompat record = new AccessibilityRecordCompat(event); - final int virtualDescendantId = getIdForItem(item); - - // Ensure the client has good defaults. - event.setEnabled(true); - - // Allow the client to populate the event. - populateEventForItem(item, event); - - if (event.getText().isEmpty() && TextUtils.isEmpty(event.getContentDescription())) { - throw new RuntimeException( - "You must add text or a content description in populateEventForItem()"); - } - - // Don't allow the client to override these properties. - event.setClassName(item.getClass().getName()); - event.setPackageName(mParentView.getContext().getPackageName()); - record.setSource(mParentView, virtualDescendantId); - - return event; - } - - private AccessibilityNodeInfoCompat getNodeForParent() { - final AccessibilityNodeInfoCompat info = AccessibilityNodeInfoCompat.obtain(mParentView); - ViewCompat.onInitializeAccessibilityNodeInfo(mParentView, info); - - final LinkedList<T> items = new LinkedList<T>(); - getVisibleItems(items); - - for (T item : items) { - final int virtualDescendantId = getIdForItem(item); - info.addChild(mParentView, virtualDescendantId); - } - - return info; - } - - private AccessibilityNodeInfoCompat populateNodeForItemInternal( - T item, AccessibilityNodeInfoCompat node) { - final int virtualDescendantId = getIdForItem(item); - - // Ensure the client has good defaults. - node.setEnabled(true); - - // Allow the client to populate the node. - populateNodeForItem(item, node); - - if (TextUtils.isEmpty(node.getText()) && TextUtils.isEmpty(node.getContentDescription())) { - throw new RuntimeException( - "You must add text or a content description in populateNodeForItem()"); - } - - // Don't allow the client to override these properties. - node.setPackageName(mParentView.getContext().getPackageName()); - node.setClassName(item.getClass().getName()); - node.setParent(mParentView); - node.setSource(mParentView, virtualDescendantId); - - if (mFocusedItemId == virtualDescendantId) { - node.addAction(AccessibilityNodeInfoCompat.ACTION_CLEAR_ACCESSIBILITY_FOCUS); - } else { - node.addAction(AccessibilityNodeInfoCompat.ACTION_ACCESSIBILITY_FOCUS); - } - - node.getBoundsInParent(mTempParentRect); - if (mTempParentRect.isEmpty()) { - throw new RuntimeException("You must set parent bounds in populateNodeForItem()"); - } - - // Set the visibility based on the parent bound. - if (intersectVisibleToUser(mTempParentRect)) { - node.setVisibleToUser(true); - node.setBoundsInParent(mTempParentRect); - } - - // Calculate screen-relative bound. - mParentView.getLocationOnScreen(mTempGlobalRect); - final int offsetX = mTempGlobalRect[0]; - final int offsetY = mTempGlobalRect[1]; - mTempScreenRect.set(mTempParentRect); - mTempScreenRect.offset(offsetX, offsetY); - node.setBoundsInScreen(mTempScreenRect); - - return node; - } - - /** - * 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. - * - * @param localRect A rectangle in local (parent) coordinates. - * @return Whether the specified {@link Rect} is visible on the screen. - */ - private boolean intersectVisibleToUser(Rect localRect) { - // 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 (mParentView.getWindowVisibility() != View.VISIBLE) { - return false; - } - - // An invisible predecessor or one with alpha zero means - // that this view is not visible to the user. - Object current = this; - while (current instanceof View) { - final View view = (View) current; - // We have attach info so this view is attached and there is no - // need to check whether we reach to ViewRootImpl on the way up. - if ((view.getAlpha() <= 0) || (view.getVisibility() != View.VISIBLE)) { - return false; - } - current = view.getParent(); - } - - // If no portion of the parent is visible, this view is not visible. - if (!mParentView.getLocalVisibleRect(mTempVisibleRect)) { - return false; - } - - // Check if the view intersects the visible portion of the parent. - return localRect.intersect(mTempVisibleRect); - } - - public AccessibilityDelegateCompat getAccessibilityDelegate() { - return mDelegate; - } - - private final AccessibilityDelegateCompat mDelegate = new AccessibilityDelegateCompat() { - @Override - public void onInitializeAccessibilityEvent(View view, AccessibilityEvent event) { - super.onInitializeAccessibilityEvent(view, event); - event.setClassName(view.getClass().getName()); - } - - @Override - public void onInitializeAccessibilityNodeInfo(View view, AccessibilityNodeInfoCompat info) { - super.onInitializeAccessibilityNodeInfo(view, info); - info.setClassName(view.getClass().getName()); - } - - @Override - public AccessibilityNodeProviderCompat getAccessibilityNodeProvider(View host) { - return TouchExplorationHelper.this; - } - }; - - /** - * Performs an accessibility action on the specified item. See - * {@link AccessibilityNodeInfoCompat#performAction(int, Bundle)}. - * <p> - * The helper class automatically handles focus management resulting from - * {@link AccessibilityNodeInfoCompat#ACTION_ACCESSIBILITY_FOCUS} and - * {@link AccessibilityNodeInfoCompat#ACTION_CLEAR_ACCESSIBILITY_FOCUS}, so - * typically a developer only needs to handle actions added manually in the - * {{@link #populateNodeForItem(Object, AccessibilityNodeInfoCompat)} - * method. - * </p> - * - * @param item The item on which to perform the action. - * @param action The accessibility action to perform. - * @param arguments Arguments for the action, or optionally {@code null}. - * @return {@code true} if the action was performed successfully. - */ - protected abstract boolean performActionForItem(T item, int action, Bundle arguments); - - /** - * Populates an event with information about the specified item. - * <p> - * At a minimum, a developer must populate the event text by doing one of - * the following: - * <ul> - * <li>appending text to {@link AccessibilityEvent#getText()}</li> - * <li>populating a description with - * {@link AccessibilityEvent#setContentDescription(CharSequence)}</li> - * </ul> - * </p> - * - * @param item The item for which to populate the event. - * @param event The event to populate. - */ - protected abstract void populateEventForItem(T item, AccessibilityEvent event); - - /** - * Populates a node with information about the specified item. - * <p> - * At a minimum, a developer must: - * <ul> - * <li>populate the event text using - * {@link AccessibilityNodeInfoCompat#setText(CharSequence)} or - * {@link AccessibilityNodeInfoCompat#setContentDescription(CharSequence)} - * </li> - * <li>set the item's parent-relative bounds using - * {@link AccessibilityNodeInfoCompat#setBoundsInParent(Rect)} - * </ul> - * - * @param item The item for which to populate the node. - * @param node The node to populate. - */ - protected abstract void populateNodeForItem(T item, AccessibilityNodeInfoCompat node); - - /** - * Populates a list with the parent view's visible items. - * <p> - * The result of this method is cached until the developer calls - * {@link #invalidateParent()}. - * </p> - * - * @param items The list to populate with visible items. - */ - protected abstract void getVisibleItems(List<T> items); - - /** - * Returns the item under the specified parent-relative coordinates. - * - * @param x The parent-relative x coordinate. - * @param y The parent-relative y coordinate. - * @return The item under coordinates (x,y). - */ - protected abstract T getItemAt(float x, float y); - - /** - * Returns the unique identifier for an item. If the specified item does not - * exist, returns {@link #INVALID_ID}. - * <p> - * This result of this method must be consistent with - * {@link #getItemForId(int)}. - * </p> - * - * @param item The item whose identifier to return. - * @return A unique identifier, or {@link #INVALID_ID}. - */ - protected abstract int getIdForItem(T item); - - /** - * Returns the item for a unique identifier. If the specified item does not - * exist, returns {@code null}. - * - * @param id The identifier for the item to return. - * @return An item, or {@code null}. - */ - protected abstract T getItemForId(int id); -} |