2013-08-28 00:14:00 +00:00
|
|
|
/*
|
|
|
|
* Copyright (C) 2013 The Android Open Source Project
|
|
|
|
*
|
|
|
|
* 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.
|
|
|
|
*/
|
|
|
|
|
2014-05-14 10:32:00 +00:00
|
|
|
package com.android.inputmethod.keyboard.emoji;
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2014-10-23 09:37:32 +00:00
|
|
|
import static com.android.inputmethod.latin.common.Constants.NOT_A_COORDINATE;
|
2013-08-28 00:14:00 +00:00
|
|
|
|
|
|
|
import android.content.Context;
|
|
|
|
import android.content.res.Resources;
|
|
|
|
import android.content.res.TypedArray;
|
2013-09-16 08:13:41 +00:00
|
|
|
import android.preference.PreferenceManager;
|
2013-08-28 00:14:00 +00:00
|
|
|
import android.support.v4.view.ViewPager;
|
|
|
|
import android.util.AttributeSet;
|
2013-09-13 12:49:53 +00:00
|
|
|
import android.util.Pair;
|
2014-02-06 09:14:26 +00:00
|
|
|
import android.util.TypedValue;
|
2013-08-28 00:14:00 +00:00
|
|
|
import android.view.LayoutInflater;
|
2013-09-20 09:35:28 +00:00
|
|
|
import android.view.MotionEvent;
|
2013-08-28 00:14:00 +00:00
|
|
|
import android.view.View;
|
2014-05-14 07:47:12 +00:00
|
|
|
import android.widget.ImageButton;
|
2013-08-28 00:14:00 +00:00
|
|
|
import android.widget.ImageView;
|
|
|
|
import android.widget.LinearLayout;
|
|
|
|
import android.widget.TabHost;
|
|
|
|
import android.widget.TabHost.OnTabChangeListener;
|
2014-05-23 07:04:39 +00:00
|
|
|
import android.widget.TabWidget;
|
2013-08-28 00:14:00 +00:00
|
|
|
import android.widget.TextView;
|
|
|
|
|
2014-05-14 10:32:00 +00:00
|
|
|
import com.android.inputmethod.keyboard.Key;
|
|
|
|
import com.android.inputmethod.keyboard.KeyboardActionListener;
|
|
|
|
import com.android.inputmethod.keyboard.KeyboardLayoutSet;
|
|
|
|
import com.android.inputmethod.keyboard.KeyboardView;
|
2014-02-24 08:24:49 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
|
|
|
|
import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
|
2014-05-14 07:47:12 +00:00
|
|
|
import com.android.inputmethod.keyboard.internal.KeyboardIconsSet;
|
2014-06-09 14:25:02 +00:00
|
|
|
import com.android.inputmethod.latin.AudioAndHapticFeedbackManager;
|
2013-08-28 00:14:00 +00:00
|
|
|
import com.android.inputmethod.latin.R;
|
2014-11-06 04:16:20 +00:00
|
|
|
import com.android.inputmethod.latin.RichInputMethodSubtype;
|
2014-10-23 09:37:32 +00:00
|
|
|
import com.android.inputmethod.latin.common.Constants;
|
2013-08-28 00:14:00 +00:00
|
|
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
|
|
|
|
|
|
|
/**
|
2013-10-07 02:28:57 +00:00
|
|
|
* View class to implement Emoji palettes.
|
2014-05-16 01:32:04 +00:00
|
|
|
* The Emoji keyboard consists of group of views layout/emoji_palettes_view.
|
2013-08-28 00:14:00 +00:00
|
|
|
* <ol>
|
|
|
|
* <li> Emoji category tabs.
|
|
|
|
* <li> Delete button.
|
|
|
|
* <li> Emoji keyboard pages that can be scrolled by swiping horizontally or by selecting a tab.
|
|
|
|
* <li> Back to main keyboard button and enter button.
|
|
|
|
* </ol>
|
|
|
|
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
|
|
|
|
*/
|
2013-10-07 02:28:57 +00:00
|
|
|
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
|
2014-01-27 09:53:44 +00:00
|
|
|
ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
|
2014-01-08 07:39:55 +00:00
|
|
|
EmojiPageKeyboardView.OnKeyEventListener {
|
2014-05-14 06:30:37 +00:00
|
|
|
private final int mFunctionalKeyBackgroundId;
|
|
|
|
private final int mSpacebarBackgroundId;
|
2014-05-23 07:04:39 +00:00
|
|
|
private final boolean mCategoryIndicatorEnabled;
|
|
|
|
private final int mCategoryIndicatorDrawableResId;
|
|
|
|
private final int mCategoryIndicatorBackgroundResId;
|
|
|
|
private final int mCategoryPageIndicatorColor;
|
|
|
|
private final int mCategoryPageIndicatorBackground;
|
2013-10-07 02:28:57 +00:00
|
|
|
private EmojiPalettesAdapter mEmojiPalettesAdapter;
|
2013-12-13 08:09:16 +00:00
|
|
|
private final EmojiLayoutParams mEmojiLayoutParams;
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2014-05-14 07:47:12 +00:00
|
|
|
private ImageButton mDeleteKey;
|
2014-02-06 09:14:26 +00:00
|
|
|
private TextView mAlphabetKeyLeft;
|
|
|
|
private TextView mAlphabetKeyRight;
|
2014-05-29 14:24:08 +00:00
|
|
|
private View mSpacebar;
|
|
|
|
// TODO: Remove this workaround.
|
|
|
|
private View mSpacebarIcon;
|
2013-08-28 00:14:00 +00:00
|
|
|
private TabHost mTabHost;
|
|
|
|
private ViewPager mEmojiPager;
|
2013-10-08 11:58:47 +00:00
|
|
|
private int mCurrentPagerPosition = 0;
|
2013-09-18 08:02:37 +00:00
|
|
|
private EmojiCategoryPageIndicatorView mEmojiCategoryPageIndicatorView;
|
2013-08-28 00:14:00 +00:00
|
|
|
|
|
|
|
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
|
|
|
|
|
2013-09-13 10:06:22 +00:00
|
|
|
private final EmojiCategory mEmojiCategory;
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2013-10-07 02:28:57 +00:00
|
|
|
public EmojiPalettesView(final Context context, final AttributeSet attrs) {
|
|
|
|
this(context, attrs, R.attr.emojiPalettesViewStyle);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
2013-10-07 02:28:57 +00:00
|
|
|
public EmojiPalettesView(final Context context, final AttributeSet attrs, final int defStyle) {
|
2013-08-28 00:14:00 +00:00
|
|
|
super(context, attrs, defStyle);
|
|
|
|
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
|
|
|
|
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
2014-05-14 06:30:37 +00:00
|
|
|
final int keyBackgroundId = keyboardViewAttr.getResourceId(
|
2013-08-28 00:14:00 +00:00
|
|
|
R.styleable.KeyboardView_keyBackground, 0);
|
2014-05-14 06:30:37 +00:00
|
|
|
mFunctionalKeyBackgroundId = keyboardViewAttr.getResourceId(
|
|
|
|
R.styleable.KeyboardView_functionalKeyBackground, keyBackgroundId);
|
|
|
|
mSpacebarBackgroundId = keyboardViewAttr.getResourceId(
|
|
|
|
R.styleable.KeyboardView_spacebarBackground, keyBackgroundId);
|
2013-08-28 00:14:00 +00:00
|
|
|
keyboardViewAttr.recycle();
|
|
|
|
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
|
|
|
|
context, null /* editorInfo */);
|
|
|
|
final Resources res = context.getResources();
|
2013-12-13 08:09:16 +00:00
|
|
|
mEmojiLayoutParams = new EmojiLayoutParams(res);
|
2014-11-06 04:16:20 +00:00
|
|
|
builder.setSubtype(RichInputMethodSubtype.getEmojiSubtype());
|
2014-12-09 08:53:24 +00:00
|
|
|
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
|
|
|
|
mEmojiLayoutParams.mEmojiKeyboardHeight);
|
2014-05-16 01:32:04 +00:00
|
|
|
final KeyboardLayoutSet layoutSet = builder.build();
|
|
|
|
final TypedArray emojiPalettesViewAttr = context.obtainStyledAttributes(attrs,
|
|
|
|
R.styleable.EmojiPalettesView, defStyle, R.style.EmojiPalettesView);
|
2013-09-16 08:13:41 +00:00
|
|
|
mEmojiCategory = new EmojiCategory(PreferenceManager.getDefaultSharedPreferences(context),
|
2014-05-16 01:32:04 +00:00
|
|
|
res, layoutSet, emojiPalettesViewAttr);
|
2014-05-23 07:04:39 +00:00
|
|
|
mCategoryIndicatorEnabled = emojiPalettesViewAttr.getBoolean(
|
|
|
|
R.styleable.EmojiPalettesView_categoryIndicatorEnabled, false);
|
|
|
|
mCategoryIndicatorDrawableResId = emojiPalettesViewAttr.getResourceId(
|
|
|
|
R.styleable.EmojiPalettesView_categoryIndicatorDrawable, 0);
|
|
|
|
mCategoryIndicatorBackgroundResId = emojiPalettesViewAttr.getResourceId(
|
|
|
|
R.styleable.EmojiPalettesView_categoryIndicatorBackground, 0);
|
|
|
|
mCategoryPageIndicatorColor = emojiPalettesViewAttr.getColor(
|
|
|
|
R.styleable.EmojiPalettesView_categoryPageIndicatorColor, 0);
|
|
|
|
mCategoryPageIndicatorBackground = emojiPalettesViewAttr.getColor(
|
|
|
|
R.styleable.EmojiPalettesView_categoryPageIndicatorBackground, 0);
|
2014-05-16 01:32:04 +00:00
|
|
|
emojiPalettesViewAttr.recycle();
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
|
|
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
|
|
|
final Resources res = getContext().getResources();
|
|
|
|
// The main keyboard expands to the entire this {@link KeyboardView}.
|
2014-12-09 08:53:24 +00:00
|
|
|
final int width = ResourceUtils.getDefaultKeyboardWidth(res)
|
2013-08-28 00:14:00 +00:00
|
|
|
+ getPaddingLeft() + getPaddingRight();
|
|
|
|
final int height = ResourceUtils.getDefaultKeyboardHeight(res)
|
2013-12-13 08:09:16 +00:00
|
|
|
+ res.getDimensionPixelSize(R.dimen.config_suggestions_strip_height)
|
2013-08-28 00:14:00 +00:00
|
|
|
+ getPaddingTop() + getPaddingBottom();
|
|
|
|
setMeasuredDimension(width, height);
|
|
|
|
}
|
|
|
|
|
2013-09-16 08:13:41 +00:00
|
|
|
private void addTab(final TabHost host, final int categoryId) {
|
2014-10-20 05:48:56 +00:00
|
|
|
final String tabId = EmojiCategory.getCategoryName(categoryId, 0 /* categoryPageId */);
|
2013-08-28 00:14:00 +00:00
|
|
|
final TabHost.TabSpec tspec = host.newTabSpec(tabId);
|
|
|
|
tspec.setContent(R.id.emoji_keyboard_dummy);
|
2014-05-16 01:32:04 +00:00
|
|
|
final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
|
|
|
|
R.layout.emoji_keyboard_tab_icon, null);
|
|
|
|
iconView.setImageResource(mEmojiCategory.getCategoryTabIcon(categoryId));
|
|
|
|
iconView.setContentDescription(mEmojiCategory.getAccessibilityDescription(categoryId));
|
|
|
|
tspec.setIndicator(iconView);
|
2013-08-28 00:14:00 +00:00
|
|
|
host.addTab(tspec);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
protected void onFinishInflate() {
|
|
|
|
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
|
|
|
|
mTabHost.setup();
|
2014-05-14 04:11:41 +00:00
|
|
|
for (final EmojiCategory.CategoryProperties properties
|
|
|
|
: mEmojiCategory.getShownCategories()) {
|
2013-09-16 08:13:41 +00:00
|
|
|
addTab(mTabHost, properties.mCategoryId);
|
2013-09-06 11:16:05 +00:00
|
|
|
}
|
2013-08-28 00:14:00 +00:00
|
|
|
mTabHost.setOnTabChangedListener(this);
|
2014-05-23 07:04:39 +00:00
|
|
|
final TabWidget tabWidget = mTabHost.getTabWidget();
|
|
|
|
tabWidget.setStripEnabled(mCategoryIndicatorEnabled);
|
|
|
|
if (mCategoryIndicatorEnabled) {
|
|
|
|
// On TabWidget's strip, what looks like an indicator is actually a background.
|
|
|
|
// And what looks like a background are actually left and right drawables.
|
|
|
|
tabWidget.setBackgroundResource(mCategoryIndicatorDrawableResId);
|
|
|
|
tabWidget.setLeftStripDrawable(mCategoryIndicatorBackgroundResId);
|
|
|
|
tabWidget.setRightStripDrawable(mCategoryIndicatorBackgroundResId);
|
|
|
|
}
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2013-12-13 08:09:16 +00:00
|
|
|
mEmojiPalettesAdapter = new EmojiPalettesAdapter(mEmojiCategory, this);
|
2013-09-12 12:11:43 +00:00
|
|
|
|
2013-08-28 00:14:00 +00:00
|
|
|
mEmojiPager = (ViewPager)findViewById(R.id.emoji_keyboard_pager);
|
2013-10-07 02:28:57 +00:00
|
|
|
mEmojiPager.setAdapter(mEmojiPalettesAdapter);
|
2013-08-28 00:14:00 +00:00
|
|
|
mEmojiPager.setOnPageChangeListener(this);
|
|
|
|
mEmojiPager.setOffscreenPageLimit(0);
|
2013-12-13 08:09:16 +00:00
|
|
|
mEmojiPager.setPersistentDrawingCache(PERSISTENT_NO_CACHE);
|
|
|
|
mEmojiLayoutParams.setPagerProperties(mEmojiPager);
|
2013-09-18 08:02:37 +00:00
|
|
|
|
|
|
|
mEmojiCategoryPageIndicatorView =
|
|
|
|
(EmojiCategoryPageIndicatorView)findViewById(R.id.emoji_category_page_id_view);
|
2014-05-23 07:04:39 +00:00
|
|
|
mEmojiCategoryPageIndicatorView.setColors(
|
|
|
|
mCategoryPageIndicatorColor, mCategoryPageIndicatorBackground);
|
2013-12-13 08:09:16 +00:00
|
|
|
mEmojiLayoutParams.setCategoryPageIdViewProperties(mEmojiCategoryPageIndicatorView);
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2013-09-16 08:13:41 +00:00
|
|
|
setCurrentCategoryId(mEmojiCategory.getCurrentCategoryId(), true /* force */);
|
2013-08-28 00:14:00 +00:00
|
|
|
|
2013-09-10 08:55:44 +00:00
|
|
|
final LinearLayout actionBar = (LinearLayout)findViewById(R.id.emoji_action_bar);
|
2013-12-13 08:09:16 +00:00
|
|
|
mEmojiLayoutParams.setActionBarProperties(actionBar);
|
2013-09-10 08:55:44 +00:00
|
|
|
|
2014-01-27 09:53:44 +00:00
|
|
|
// deleteKey depends only on OnTouchListener.
|
2014-05-14 07:47:12 +00:00
|
|
|
mDeleteKey = (ImageButton)findViewById(R.id.emoji_keyboard_delete);
|
|
|
|
mDeleteKey.setBackgroundResource(mFunctionalKeyBackgroundId);
|
|
|
|
mDeleteKey.setTag(Constants.CODE_DELETE);
|
2015-01-31 01:20:12 +00:00
|
|
|
mDeleteKey.setOnTouchListener(this);
|
2014-01-27 09:53:44 +00:00
|
|
|
|
2014-02-06 09:14:26 +00:00
|
|
|
// {@link #mAlphabetKeyLeft}, {@link #mAlphabetKeyRight, and spaceKey depend 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 does not occur
|
|
|
|
// if the event is canceled by moving off the finger from the view.
|
|
|
|
// The text on alphabet keys are set at
|
|
|
|
// {@link #startEmojiPalettes(String,int,float,Typeface)}.
|
|
|
|
mAlphabetKeyLeft = (TextView)findViewById(R.id.emoji_keyboard_alphabet_left);
|
2014-05-14 06:30:37 +00:00
|
|
|
mAlphabetKeyLeft.setBackgroundResource(mFunctionalKeyBackgroundId);
|
2014-02-06 09:14:26 +00:00
|
|
|
mAlphabetKeyLeft.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
|
|
|
|
mAlphabetKeyLeft.setOnTouchListener(this);
|
|
|
|
mAlphabetKeyLeft.setOnClickListener(this);
|
|
|
|
mAlphabetKeyRight = (TextView)findViewById(R.id.emoji_keyboard_alphabet_right);
|
2014-05-14 06:30:37 +00:00
|
|
|
mAlphabetKeyRight.setBackgroundResource(mFunctionalKeyBackgroundId);
|
2014-02-06 09:14:26 +00:00
|
|
|
mAlphabetKeyRight.setTag(Constants.CODE_ALPHA_FROM_EMOJI);
|
|
|
|
mAlphabetKeyRight.setOnTouchListener(this);
|
|
|
|
mAlphabetKeyRight.setOnClickListener(this);
|
2014-05-29 14:24:08 +00:00
|
|
|
mSpacebar = findViewById(R.id.emoji_keyboard_space);
|
2014-05-14 07:47:12 +00:00
|
|
|
mSpacebar.setBackgroundResource(mSpacebarBackgroundId);
|
|
|
|
mSpacebar.setTag(Constants.CODE_SPACE);
|
|
|
|
mSpacebar.setOnTouchListener(this);
|
|
|
|
mSpacebar.setOnClickListener(this);
|
|
|
|
mEmojiLayoutParams.setKeyProperties(mSpacebar);
|
2014-05-29 14:24:08 +00:00
|
|
|
mSpacebarIcon = findViewById(R.id.emoji_keyboard_space_icon);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
2014-04-07 03:41:51 +00:00
|
|
|
@Override
|
|
|
|
public boolean dispatchTouchEvent(final MotionEvent ev) {
|
|
|
|
// Add here to the stack trace to nail down the {@link IllegalArgumentException} exception
|
|
|
|
// in MotionEvent that sporadically happens.
|
|
|
|
// TODO: Remove this override method once the issue has been addressed.
|
|
|
|
return super.dispatchTouchEvent(ev);
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:14:00 +00:00
|
|
|
@Override
|
|
|
|
public void onTabChanged(final String tabId) {
|
2014-06-09 14:25:02 +00:00
|
|
|
AudioAndHapticFeedbackManager.getInstance().performHapticAndAudioFeedback(
|
|
|
|
Constants.CODE_UNSPECIFIED, this);
|
2013-09-16 08:13:41 +00:00
|
|
|
final int categoryId = mEmojiCategory.getCategoryId(tabId);
|
|
|
|
setCurrentCategoryId(categoryId, false /* force */);
|
2013-09-18 08:02:37 +00:00
|
|
|
updateEmojiCategoryPageIdView();
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageSelected(final int position) {
|
2013-09-16 08:13:41 +00:00
|
|
|
final Pair<Integer, Integer> newPos =
|
|
|
|
mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
|
|
|
|
setCurrentCategoryId(newPos.first /* categoryId */, false /* force */);
|
|
|
|
mEmojiCategory.setCurrentCategoryPageId(newPos.second /* categoryPageId */);
|
2013-09-18 08:02:37 +00:00
|
|
|
updateEmojiCategoryPageIdView();
|
2013-10-08 11:58:47 +00:00
|
|
|
mCurrentPagerPosition = position;
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageScrollStateChanged(final int state) {
|
|
|
|
// Ignore this message. Only want the actual page selected.
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public void onPageScrolled(final int position, final float positionOffset,
|
2015-02-03 18:18:06 +00:00
|
|
|
final int positionOffsetPixels) {
|
2014-02-12 09:38:37 +00:00
|
|
|
mEmojiPalettesAdapter.onPageScrolled();
|
2013-09-18 08:02:37 +00:00
|
|
|
final Pair<Integer, Integer> newPos =
|
|
|
|
mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position);
|
|
|
|
final int newCategoryId = newPos.first;
|
|
|
|
final int newCategorySize = mEmojiCategory.getCategoryPageSize(newCategoryId);
|
|
|
|
final int currentCategoryId = mEmojiCategory.getCurrentCategoryId();
|
|
|
|
final int currentCategoryPageId = mEmojiCategory.getCurrentCategoryPageId();
|
|
|
|
final int currentCategorySize = mEmojiCategory.getCurrentCategoryPageSize();
|
|
|
|
if (newCategoryId == currentCategoryId) {
|
|
|
|
mEmojiCategoryPageIndicatorView.setCategoryPageId(
|
|
|
|
newCategorySize, newPos.second, positionOffset);
|
|
|
|
} else if (newCategoryId > currentCategoryId) {
|
|
|
|
mEmojiCategoryPageIndicatorView.setCategoryPageId(
|
|
|
|
currentCategorySize, currentCategoryPageId, positionOffset);
|
|
|
|
} else if (newCategoryId < currentCategoryId) {
|
|
|
|
mEmojiCategoryPageIndicatorView.setCategoryPageId(
|
|
|
|
currentCategorySize, currentCategoryPageId, positionOffset - 1);
|
|
|
|
}
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
2014-01-27 09:53:44 +00:00
|
|
|
/**
|
|
|
|
* 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.
|
|
|
|
*/
|
2013-08-28 00:14:00 +00:00
|
|
|
@Override
|
2014-01-08 07:39:55 +00:00
|
|
|
public boolean onTouch(final View v, final MotionEvent event) {
|
2014-01-27 09:53:44 +00:00
|
|
|
if (event.getActionMasked() != MotionEvent.ACTION_DOWN) {
|
|
|
|
return false;
|
|
|
|
}
|
2014-01-08 07:39:55 +00:00
|
|
|
final Object tag = v.getTag();
|
|
|
|
if (!(tag instanceof Integer)) {
|
|
|
|
return false;
|
|
|
|
}
|
|
|
|
final int code = (Integer) tag;
|
2014-01-27 09:53:44 +00:00
|
|
|
mKeyboardActionListener.onPressKey(
|
|
|
|
code, 0 /* repeatCount */, true /* isSinglePointer */);
|
|
|
|
// It's important to return false here. Otherwise, {@link #onClick} and touch-down visual
|
|
|
|
// feedback stop working.
|
2014-01-08 07:39:55 +00:00
|
|
|
return false;
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
2014-01-27 09:53:44 +00:00
|
|
|
/**
|
|
|
|
* Called from {@link EmojiPageKeyboardView} through {@link android.view.View.OnClickListener}
|
|
|
|
* 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;
|
2014-03-31 10:43:12 +00:00
|
|
|
mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE,
|
|
|
|
false /* isKeyRepeat */);
|
2014-01-27 09:53:44 +00:00
|
|
|
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Called from {@link EmojiPageKeyboardView} through
|
2014-05-14 10:32:00 +00:00
|
|
|
* {@link com.android.inputmethod.keyboard.emoji.EmojiPageKeyboardView.OnKeyEventListener}
|
2014-01-27 09:53:44 +00:00
|
|
|
* interface to handle touch events from non-View-based elements such as Emoji buttons.
|
|
|
|
*/
|
2014-01-08 07:39:55 +00:00
|
|
|
@Override
|
|
|
|
public void onPressKey(final Key key) {
|
|
|
|
final int code = key.getCode();
|
2013-08-28 00:14:00 +00:00
|
|
|
mKeyboardActionListener.onPressKey(code, 0 /* repeatCount */, true /* isSinglePointer */);
|
|
|
|
}
|
|
|
|
|
2014-01-27 09:53:44 +00:00
|
|
|
/**
|
|
|
|
* Called from {@link EmojiPageKeyboardView} through
|
2014-05-14 10:32:00 +00:00
|
|
|
* {@link com.android.inputmethod.keyboard.emoji.EmojiPageKeyboardView.OnKeyEventListener}
|
2014-01-27 09:53:44 +00:00
|
|
|
* interface to handle touch events from non-View-based elements such as Emoji buttons.
|
|
|
|
*/
|
2013-08-28 00:14:00 +00:00
|
|
|
@Override
|
2014-01-08 07:39:55 +00:00
|
|
|
public void onReleaseKey(final Key key) {
|
2013-10-07 02:28:57 +00:00
|
|
|
mEmojiPalettesAdapter.addRecentKey(key);
|
2013-09-16 08:13:41 +00:00
|
|
|
mEmojiCategory.saveLastTypedCategoryPage();
|
2013-08-28 00:14:00 +00:00
|
|
|
final int code = key.getCode();
|
|
|
|
if (code == Constants.CODE_OUTPUT_TEXT) {
|
|
|
|
mKeyboardActionListener.onTextInput(key.getOutputText());
|
2014-01-08 07:39:55 +00:00
|
|
|
} else {
|
2014-03-31 10:43:12 +00:00
|
|
|
mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE,
|
|
|
|
false /* isKeyRepeat */);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
2014-01-08 07:39:55 +00:00
|
|
|
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void setHardwareAcceleratedDrawingEnabled(final boolean enabled) {
|
2014-03-27 08:21:39 +00:00
|
|
|
if (!enabled) return;
|
|
|
|
// TODO: Should use LAYER_TYPE_SOFTWARE when hardware acceleration is off?
|
|
|
|
setLayerType(LAYER_TYPE_HARDWARE, null);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
|
2014-02-24 08:24:49 +00:00
|
|
|
private static void setupAlphabetKey(final TextView alphabetKey, final String label,
|
2015-02-03 18:18:06 +00:00
|
|
|
final KeyDrawParams params) {
|
2014-02-24 08:24:49 +00:00
|
|
|
alphabetKey.setText(label);
|
2014-05-16 01:32:04 +00:00
|
|
|
alphabetKey.setTextColor(params.mFunctionalTextColor);
|
2014-02-24 08:24:49 +00:00
|
|
|
alphabetKey.setTextSize(TypedValue.COMPLEX_UNIT_PX, params.mLabelSize);
|
|
|
|
alphabetKey.setTypeface(params.mTypeface);
|
|
|
|
}
|
|
|
|
|
|
|
|
public void startEmojiPalettes(final String switchToAlphaLabel,
|
2015-02-03 18:18:06 +00:00
|
|
|
final KeyVisualAttributes keyVisualAttr, final KeyboardIconsSet iconSet) {
|
2014-05-29 14:24:08 +00:00
|
|
|
final int deleteIconResId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_DELETE_KEY);
|
|
|
|
if (deleteIconResId != 0) {
|
|
|
|
mDeleteKey.setImageResource(deleteIconResId);
|
|
|
|
}
|
|
|
|
final int spacebarResId = iconSet.getIconResourceId(KeyboardIconsSet.NAME_SPACE_KEY);
|
|
|
|
if (spacebarResId != 0) {
|
2014-05-29 14:24:08 +00:00
|
|
|
// TODO: Remove this workaround to place the spacebar icon.
|
|
|
|
mSpacebarIcon.setBackgroundResource(spacebarResId);
|
2014-05-29 14:24:08 +00:00
|
|
|
}
|
2014-02-24 08:24:49 +00:00
|
|
|
final KeyDrawParams params = new KeyDrawParams();
|
|
|
|
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
|
|
|
|
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
|
|
|
|
setupAlphabetKey(mAlphabetKeyRight, switchToAlphaLabel, params);
|
2013-10-08 11:11:35 +00:00
|
|
|
mEmojiPager.setAdapter(mEmojiPalettesAdapter);
|
2013-10-08 11:58:47 +00:00
|
|
|
mEmojiPager.setCurrentItem(mCurrentPagerPosition);
|
2013-10-08 11:11:35 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
public void stopEmojiPalettes() {
|
2014-05-23 18:01:48 +00:00
|
|
|
mEmojiPalettesAdapter.releaseCurrentKey(true /* withKeyRegistering */);
|
2013-10-08 11:58:47 +00:00
|
|
|
mEmojiPalettesAdapter.flushPendingRecentKeys();
|
2013-10-08 11:11:35 +00:00
|
|
|
mEmojiPager.setAdapter(null);
|
|
|
|
}
|
|
|
|
|
2013-08-28 00:14:00 +00:00
|
|
|
public void setKeyboardActionListener(final KeyboardActionListener listener) {
|
|
|
|
mKeyboardActionListener = listener;
|
|
|
|
}
|
|
|
|
|
2013-09-18 08:02:37 +00:00
|
|
|
private void updateEmojiCategoryPageIdView() {
|
|
|
|
if (mEmojiCategoryPageIndicatorView == null) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
mEmojiCategoryPageIndicatorView.setCategoryPageId(
|
|
|
|
mEmojiCategory.getCurrentCategoryPageSize(),
|
|
|
|
mEmojiCategory.getCurrentCategoryPageId(), 0.0f /* offset */);
|
|
|
|
}
|
|
|
|
|
2013-09-16 08:13:41 +00:00
|
|
|
private void setCurrentCategoryId(final int categoryId, final boolean force) {
|
2013-10-04 09:16:54 +00:00
|
|
|
final int oldCategoryId = mEmojiCategory.getCurrentCategoryId();
|
|
|
|
if (oldCategoryId == categoryId && !force) {
|
2013-08-28 00:14:00 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2014-05-14 04:11:41 +00:00
|
|
|
if (oldCategoryId == EmojiCategory.ID_RECENTS) {
|
2013-10-04 09:16:54 +00:00
|
|
|
// Needs to save pending updates for recent keys when we get out of the recents
|
|
|
|
// category because we don't want to move the recent emojis around while the user
|
|
|
|
// is in the recents category.
|
2013-10-07 03:48:14 +00:00
|
|
|
mEmojiPalettesAdapter.flushPendingRecentKeys();
|
2013-10-04 09:16:54 +00:00
|
|
|
}
|
|
|
|
|
2013-09-16 08:13:41 +00:00
|
|
|
mEmojiCategory.setCurrentCategoryId(categoryId);
|
|
|
|
final int newTabId = mEmojiCategory.getTabIdFromCategoryId(categoryId);
|
|
|
|
final int newCategoryPageId = mEmojiCategory.getPageIdFromCategoryId(categoryId);
|
2013-09-13 12:49:53 +00:00
|
|
|
if (force || mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(
|
2013-09-16 08:13:41 +00:00
|
|
|
mEmojiPager.getCurrentItem()).first != categoryId) {
|
2013-09-17 02:43:11 +00:00
|
|
|
mEmojiPager.setCurrentItem(newCategoryPageId, false /* smoothScroll */);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
2013-09-12 12:11:43 +00:00
|
|
|
if (force || mTabHost.getCurrentTab() != newTabId) {
|
|
|
|
mTabHost.setCurrentTab(newTabId);
|
2013-08-28 00:14:00 +00:00
|
|
|
}
|
|
|
|
}
|
2015-02-03 18:18:06 +00:00
|
|
|
}
|