Fix inconsistent behavior with the spacebar on the Emoji pallete.

On the Emoji palette, unlike other layouts, a user could not
cancel events by moving the finger away from the spacebar.

With this patch, the actual handler of the spacebar will be
registered as onClick event, which will not occur when the user
cancel the event.

Bug: 12464067
Change-Id: I7e7e11ae5f17073e5d92116adca0702579d3ae9c
This commit is contained in:
Yohei Yukawa 2014-01-27 18:53:44 +09:00
parent a3a85e8c2b
commit 0e04c24a05

View file

@ -73,7 +73,7 @@ import java.util.concurrent.TimeUnit;
* Because of the above reasons, this class doesn't extend {@link KeyboardView}. * Because of the above reasons, this class doesn't extend {@link KeyboardView}.
*/ */
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener, public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
ViewPager.OnPageChangeListener, View.OnTouchListener, ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
EmojiPageKeyboardView.OnKeyEventListener { EmojiPageKeyboardView.OnKeyEventListener {
static final String TAG = EmojiPalettesView.class.getSimpleName(); static final String TAG = EmojiPalettesView.class.getSimpleName();
private static final boolean DEBUG_PAGER = false; private static final boolean DEBUG_PAGER = false;
@ -482,22 +482,35 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
final LinearLayout actionBar = (LinearLayout)findViewById(R.id.emoji_action_bar); final LinearLayout actionBar = (LinearLayout)findViewById(R.id.emoji_action_bar);
mEmojiLayoutParams.setActionBarProperties(actionBar); mEmojiLayoutParams.setActionBarProperties(actionBar);
// deleteKey depends only on OnTouchListener.
final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete); final ImageView deleteKey = (ImageView)findViewById(R.id.emoji_keyboard_delete);
deleteKey.setTag(Constants.CODE_DELETE); deleteKey.setTag(Constants.CODE_DELETE);
deleteKey.setOnTouchListener(mDeleteKeyOnTouchListener); deleteKey.setOnTouchListener(mDeleteKeyOnTouchListener);
// alphabetKey depends only on OnTouchListener as it does everything in key-press in
// ACTION_DOWN.
final ImageView alphabetKey = (ImageView)findViewById(R.id.emoji_keyboard_alphabet); final ImageView alphabetKey = (ImageView)findViewById(R.id.emoji_keyboard_alphabet);
alphabetKey.setBackgroundResource(mEmojiFunctionalKeyBackgroundId); alphabetKey.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
alphabetKey.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL); alphabetKey.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
alphabetKey.setOnTouchListener(this); alphabetKey.setOnTouchListener(this);
final ImageView spaceKey = (ImageView)findViewById(R.id.emoji_keyboard_space);
spaceKey.setBackgroundResource(mKeyBackgroundId); // alphabetKey2 depends only on OnTouchListener as it does everything in key-press in
spaceKey.setTag(Constants.CODE_SPACE); // ACTION_DOWN.
spaceKey.setOnTouchListener(this);
mEmojiLayoutParams.setKeyProperties(spaceKey);
final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2); final ImageView alphabetKey2 = (ImageView)findViewById(R.id.emoji_keyboard_alphabet2);
alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId); alphabetKey2.setBackgroundResource(mEmojiFunctionalKeyBackgroundId);
alphabetKey2.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL); alphabetKey2.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
alphabetKey2.setOnTouchListener(this); alphabetKey2.setOnTouchListener(this);
// spaceKey depends on {@link View.OnClickListener} as well as {@link View.OnTouchListener}.
// {@link View.OnTouchListener} is used as the trigger of key-press while
// {@link View.OnClickListener} is used as the trigger of key-release which may not occur
// if the event is canceled by moving off the finger from the view.
final ImageView spaceKey = (ImageView)findViewById(R.id.emoji_keyboard_space);
spaceKey.setBackgroundResource(mKeyBackgroundId);
spaceKey.setTag(Constants.CODE_SPACE);
spaceKey.setOnTouchListener(this);
spaceKey.setOnClickListener(this);
mEmojiLayoutParams.setKeyProperties(spaceKey);
} }
@Override @Override
@ -507,7 +520,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
updateEmojiCategoryPageIdView(); updateEmojiCategoryPageIdView();
} }
@Override @Override
public void onPageSelected(final int position) { public void onPageSelected(final int position) {
final Pair<Integer, Integer> newPos = final Pair<Integer, Integer> newPos =
@ -545,40 +557,62 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
} }
} }
// Called from {@link EmojiPageKeyboardView} through {@link View.OnTouchListener} interface to /**
// handle touch events from View-based elements such as the space bar. * Called from {@link EmojiPageKeyboardView} through {@link android.view.View.OnTouchListener}
* interface to handle touch events from View-based elements such as the space bar.
* Note that this method is used only for observing {@link MotionEvent#ACTION_DOWN} to trigger
* {@link KeyboardActionListener#onPressKey}. {@link KeyboardActionListener#onReleaseKey} will
* be covered by {@link #onClick} as long as the event is not canceled.
*/
@Override @Override
public boolean onTouch(final View v, final MotionEvent event) { public boolean onTouch(final View v, final MotionEvent event) {
if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
return false;
}
final Object tag = v.getTag(); final Object tag = v.getTag();
if (!(tag instanceof Integer)) { if (!(tag instanceof Integer)) {
return false; return false;
} }
final int code = (Integer) tag; final int code = (Integer) tag;
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
mKeyboardActionListener.onPressKey( mKeyboardActionListener.onPressKey(
code, 0 /* repeatCount */, true /* isSinglePointer */); code, 0 /* repeatCount */, true /* isSinglePointer */);
break; // It's important to return false here. Otherwise, {@link #onClick} and touch-down visual
case MotionEvent.ACTION_UP: // feedback stop working.
mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE);
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
break;
}
return false; return false;
} }
// Called from {@link EmojiPageKeyboardView} through /**
// {@link EmojiPageKeyboardView.OnKeyEventListener} interface to handle touch events from * Called from {@link EmojiPageKeyboardView} through {@link android.view.View.OnClickListener}
// non-View-based elements like typical Emoji characters. * interface to handle non-canceled touch-up events from View-based elements such as the space
* bar.
*/
@Override
public void onClick(View v) {
final Object tag = v.getTag();
if (!(tag instanceof Integer)) {
return;
}
final int code = (Integer) tag;
mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE);
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
}
/**
* Called from {@link EmojiPageKeyboardView} through
* {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
* interface to handle touch events from non-View-based elements such as Emoji buttons.
*/
@Override @Override
public void onPressKey(final Key key) { public void onPressKey(final Key key) {
final int code = key.getCode(); final int code = key.getCode();
mKeyboardActionListener.onPressKey(code, 0 /* repeatCount */, true /* isSinglePointer */); mKeyboardActionListener.onPressKey(code, 0 /* repeatCount */, true /* isSinglePointer */);
} }
// Called from {@link EmojiPageKeyboardView} through /**
// {@link EmojiPageKeyboardView.OnKeyEventListener} interface to handle touch events from * Called from {@link EmojiPageKeyboardView} through
// non-View-based elements like typical Emoji characters. * {@link com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView.OnKeyEventListener}
* interface to handle touch events from non-View-based elements such as Emoji buttons.
*/
@Override @Override
public void onReleaseKey(final Key key) { public void onReleaseKey(final Key key) {
mEmojiPalettesAdapter.addRecentKey(key); mEmojiPalettesAdapter.addRecentKey(key);