am 305778b5: Support accessibility TalkBack in emoji palette

* commit '305778b53a5e7c865cae4010e657d00bb9bf5075':
  Support accessibility TalkBack in emoji palette
main
Tadashi G. Takaoka 2014-05-20 09:01:01 +00:00 committed by Android Git Automerger
commit b52665bb0b
2 changed files with 39 additions and 16 deletions

View File

@ -17,6 +17,7 @@
package com.android.inputmethod.accessibility; package com.android.inputmethod.accessibility;
import android.content.Context; import android.content.Context;
import android.content.res.Resources;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log; import android.util.Log;
import android.util.SparseIntArray; import android.util.SparseIntArray;
@ -27,21 +28,18 @@ import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.keyboard.KeyboardId; import com.android.inputmethod.keyboard.KeyboardId;
import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R; import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.utils.CollectionUtils;
import java.util.HashMap; import java.util.Locale;
public final class KeyCodeDescriptionMapper { public final class KeyCodeDescriptionMapper {
private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName(); private static final String TAG = KeyCodeDescriptionMapper.class.getSimpleName();
private static final String SPOKEN_EMOJI_RESOURCE_NAME_FORMAT = "spoken_emoji_%04X";
// The resource ID of the string spoken for obscured keys // The resource ID of the string spoken for obscured keys
private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot; private static final int OBSCURED_KEY_RES_ID = R.string.spoken_description_dot;
private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper(); private static KeyCodeDescriptionMapper sInstance = new KeyCodeDescriptionMapper();
// Map of key labels to spoken description resource IDs
private final HashMap<CharSequence, Integer> mKeyLabelMap = CollectionUtils.newHashMap();
// Sparse array of spoken description resource IDs indexed by key codes // Sparse array of spoken description resource IDs indexed by key codes
private final SparseIntArray mKeyCodeMap; private final SparseIntArray mKeyCodeMap;
@ -114,17 +112,12 @@ public final class KeyCodeDescriptionMapper {
return getDescriptionForActionKey(context, keyboard, key); return getDescriptionForActionKey(context, keyboard, key);
} }
if (!TextUtils.isEmpty(key.getLabel())) { if (code == Constants.CODE_OUTPUT_TEXT) {
final String label = key.getLabel().trim(); return key.getOutputText();
// First, attempt to map the label to a pre-defined description.
if (mKeyLabelMap.containsKey(label)) {
return context.getString(mKeyLabelMap.get(label));
}
} }
// Just attempt to speak the description. // Just attempt to speak the description.
if (key.getCode() != Constants.CODE_UNSPECIFIED) { if (code != Constants.CODE_UNSPECIFIED) {
return getDescriptionForKeyCode(context, keyboard, key, shouldObscure); return getDescriptionForKeyCode(context, keyboard, key, shouldObscure);
} }
return null; return null;
@ -139,7 +132,7 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @return a character sequence describing the action performed by pressing the key * @return a character sequence describing the action performed by pressing the key
*/ */
private String getDescriptionForSwitchAlphaSymbol(final Context context, private static String getDescriptionForSwitchAlphaSymbol(final Context context,
final Keyboard keyboard) { final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId; final int elementId = keyboardId.mElementId;
@ -177,7 +170,8 @@ public final class KeyCodeDescriptionMapper {
* @param keyboard The keyboard on which the key resides. * @param keyboard The keyboard on which the key resides.
* @return A context-sensitive description of the "Shift" key. * @return A context-sensitive description of the "Shift" key.
*/ */
private String getDescriptionForShiftKey(final Context context, final Keyboard keyboard) { private static String getDescriptionForShiftKey(final Context context,
final Keyboard keyboard) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int elementId = keyboardId.mElementId; final int elementId = keyboardId.mElementId;
final int resId; final int resId;
@ -211,7 +205,7 @@ public final class KeyCodeDescriptionMapper {
* @param key The key to describe. * @param key The key to describe.
* @return Returns a context-sensitive description of the "Enter" action key. * @return Returns a context-sensitive description of the "Enter" action key.
*/ */
private String getDescriptionForActionKey(final Context context, final Keyboard keyboard, private static String getDescriptionForActionKey(final Context context, final Keyboard keyboard,
final Key key) { final Key key) {
final KeyboardId keyboardId = keyboard.mId; final KeyboardId keyboardId = keyboard.mId;
final int actionId = keyboardId.imeAction(); final int actionId = keyboardId.imeAction();
@ -280,6 +274,13 @@ public final class KeyCodeDescriptionMapper {
if (mKeyCodeMap.indexOfKey(code) >= 0) { if (mKeyCodeMap.indexOfKey(code) >= 0) {
return context.getString(mKeyCodeMap.get(code)); return context.getString(mKeyCodeMap.get(code));
} }
final int spokenEmojiId = getSpokenDescriptionId(
context, code, SPOKEN_EMOJI_RESOURCE_NAME_FORMAT);
if (spokenEmojiId != 0) {
final String spokenEmoji = context.getString(spokenEmojiId);
mKeyCodeMap.append(code, spokenEmojiId);
return spokenEmoji;
}
if (isDefinedNonCtrl) { if (isDefinedNonCtrl) {
return Character.toString((char) code); return Character.toString((char) code);
} }
@ -288,4 +289,13 @@ public final class KeyCodeDescriptionMapper {
} }
return context.getString(R.string.spoken_description_unknown, code); return context.getString(R.string.spoken_description_unknown, code);
} }
private static int getSpokenDescriptionId(final Context context, final int code,
final String resourceNameFormat) {
final String resourceName = String.format(Locale.ROOT, resourceNameFormat, code);
final Resources resources = context.getResources();
final String packageName = resources.getResourcePackageName(
R.string.spoken_description_unknown);
return resources.getIdentifier(resourceName, "string", packageName);
}
} }

View File

@ -22,6 +22,8 @@ import android.util.AttributeSet;
import android.view.GestureDetector; import android.view.GestureDetector;
import android.view.MotionEvent; import android.view.MotionEvent;
import com.android.inputmethod.accessibility.AccessibilityUtils;
import com.android.inputmethod.accessibility.KeyboardAccessibilityDelegate;
import com.android.inputmethod.keyboard.Key; import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.KeyDetector; import com.android.inputmethod.keyboard.KeyDetector;
import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.keyboard.Keyboard;
@ -53,6 +55,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
private OnKeyEventListener mListener = EMPTY_LISTENER; private OnKeyEventListener mListener = EMPTY_LISTENER;
private final KeyDetector mKeyDetector = new KeyDetector(); private final KeyDetector mKeyDetector = new KeyDetector();
private final GestureDetector mGestureDetector; private final GestureDetector mGestureDetector;
private final KeyboardAccessibilityDelegate<EmojiPageKeyboardView> mAccessibilityDelegate;
public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) { public EmojiPageKeyboardView(final Context context, final AttributeSet attrs) {
this(context, attrs, R.attr.keyboardViewStyle); this(context, attrs, R.attr.keyboardViewStyle);
@ -64,6 +67,7 @@ final class EmojiPageKeyboardView extends KeyboardView implements
mGestureDetector = new GestureDetector(context, this); mGestureDetector = new GestureDetector(context, this);
mGestureDetector.setIsLongpressEnabled(false /* isLongpressEnabled */); mGestureDetector.setIsLongpressEnabled(false /* isLongpressEnabled */);
mHandler = new Handler(); mHandler = new Handler();
mAccessibilityDelegate = new KeyboardAccessibilityDelegate<>(this, mKeyDetector);
} }
public void setOnKeyEventListener(final OnKeyEventListener listener) { public void setOnKeyEventListener(final OnKeyEventListener listener) {
@ -79,6 +83,15 @@ final class EmojiPageKeyboardView extends KeyboardView implements
mKeyDetector.setKeyboard(keyboard, 0 /* correctionX */, 0 /* correctionY */); mKeyDetector.setKeyboard(keyboard, 0 /* correctionX */, 0 /* correctionY */);
} }
@Override
public boolean dispatchHoverEvent(final MotionEvent event) {
if (!AccessibilityUtils.getInstance().isTouchExplorationEnabled()) {
// Reflection doesn't support calling superclass methods.
return false;
}
return mAccessibilityDelegate.dispatchHoverEvent(event);
}
/** /**
* {@inheritDoc} * {@inheritDoc}
*/ */