aboutsummaryrefslogtreecommitdiffstats
path: root/java/src
diff options
context:
space:
mode:
Diffstat (limited to 'java/src')
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java466
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java4
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java359
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java3
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java1
-rw-r--r--java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java147
7 files changed, 524 insertions, 459 deletions
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
index 4ef9e2232..9922f9024 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiCategoryPageIndicatorView.java
@@ -24,7 +24,8 @@ import android.graphics.Paint;
import android.util.AttributeSet;
import android.widget.LinearLayout;
-public class EmojiCategoryPageIndicatorView extends LinearLayout {
+//TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiCategoryPageIndicatorView extends LinearLayout {
private static final float BOTTOM_MARGIN_RATIO = 1.0f;
private final Paint mPaint = new Paint();
private int mCategoryPageSize = 0;
diff --git a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
index d8b5758a6..d5f166c9f 100644
--- a/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
+++ b/java/src/com/android/inputmethod/keyboard/EmojiPalettesView.java
@@ -19,50 +19,36 @@ package com.android.inputmethod.keyboard;
import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE;
import android.content.Context;
-import android.content.SharedPreferences;
import android.content.res.ColorStateList;
import android.content.res.Resources;
import android.content.res.TypedArray;
import android.graphics.Color;
-import android.graphics.Rect;
-import android.os.Build;
import android.os.CountDownTimer;
import android.preference.PreferenceManager;
-import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
-import android.util.Log;
import android.util.Pair;
-import android.util.SparseArray;
import android.util.TypedValue;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
-import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.TabHost;
import android.widget.TabHost.OnTabChangeListener;
import android.widget.TextView;
-import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard;
+import com.android.inputmethod.keyboard.internal.EmojiCategory;
import com.android.inputmethod.keyboard.internal.EmojiLayoutParams;
import com.android.inputmethod.keyboard.internal.EmojiPageKeyboardView;
+import com.android.inputmethod.keyboard.internal.EmojiPalettesAdapter;
import com.android.inputmethod.keyboard.internal.KeyDrawParams;
import com.android.inputmethod.keyboard.internal.KeyVisualAttributes;
import com.android.inputmethod.latin.Constants;
import com.android.inputmethod.latin.R;
import com.android.inputmethod.latin.SubtypeSwitcher;
-import com.android.inputmethod.latin.settings.Settings;
-import com.android.inputmethod.latin.utils.CollectionUtils;
import com.android.inputmethod.latin.utils.ResourceUtils;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.Comparator;
-import java.util.HashMap;
-import java.util.List;
-import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
/**
@@ -76,11 +62,10 @@ import java.util.concurrent.TimeUnit;
* </ol>
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
public final class EmojiPalettesView extends LinearLayout implements OnTabChangeListener,
ViewPager.OnPageChangeListener, View.OnClickListener, View.OnTouchListener,
EmojiPageKeyboardView.OnKeyEventListener {
- static final String TAG = EmojiPalettesView.class.getSimpleName();
- private static final boolean DEBUG_PAGER = false;
private final int mKeyBackgroundId;
private final int mEmojiFunctionalKeyBackgroundId;
private final ColorStateList mTabLabelColor;
@@ -97,317 +82,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
- private static final int CATEGORY_ID_UNSPECIFIED = -1;
- public static final int CATEGORY_ID_RECENTS = 0;
- public static final int CATEGORY_ID_PEOPLE = 1;
- public static final int CATEGORY_ID_OBJECTS = 2;
- public static final int CATEGORY_ID_NATURE = 3;
- public static final int CATEGORY_ID_PLACES = 4;
- public static final int CATEGORY_ID_SYMBOLS = 5;
- public static final int CATEGORY_ID_EMOTICONS = 6;
-
- private static class CategoryProperties {
- public int mCategoryId;
- public int mPageCount;
- public CategoryProperties(final int categoryId, final int pageCount) {
- mCategoryId = categoryId;
- mPageCount = pageCount;
- }
- }
-
- private static class EmojiCategory {
- private static final String[] sCategoryName = {
- "recents",
- "people",
- "objects",
- "nature",
- "places",
- "symbols",
- "emoticons" };
- private static final int[] sCategoryIcon = {
- R.drawable.ic_emoji_recent_light,
- R.drawable.ic_emoji_people_light,
- R.drawable.ic_emoji_objects_light,
- R.drawable.ic_emoji_nature_light,
- R.drawable.ic_emoji_places_light,
- R.drawable.ic_emoji_symbols_light,
- 0 };
- private static final String[] sCategoryLabel =
- { null, null, null, null, null, null, ":-)" };
- private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
- R.string.spoken_descrption_emoji_category_recents,
- R.string.spoken_descrption_emoji_category_people,
- R.string.spoken_descrption_emoji_category_objects,
- R.string.spoken_descrption_emoji_category_nature,
- R.string.spoken_descrption_emoji_category_places,
- R.string.spoken_descrption_emoji_category_symbols,
- R.string.spoken_descrption_emoji_category_emoticons };
- private static final int[] sCategoryElementId = {
- KeyboardId.ELEMENT_EMOJI_RECENTS,
- KeyboardId.ELEMENT_EMOJI_CATEGORY1,
- KeyboardId.ELEMENT_EMOJI_CATEGORY2,
- KeyboardId.ELEMENT_EMOJI_CATEGORY3,
- KeyboardId.ELEMENT_EMOJI_CATEGORY4,
- KeyboardId.ELEMENT_EMOJI_CATEGORY5,
- KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
- private final SharedPreferences mPrefs;
- private final Resources mRes;
- private final int mMaxPageKeyCount;
- private final KeyboardLayoutSet mLayoutSet;
- private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
- private final ArrayList<CategoryProperties> mShownCategories =
- CollectionUtils.newArrayList();
- private final ConcurrentHashMap<Long, DynamicGridKeyboard>
- mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
-
- private int mCurrentCategoryId = CATEGORY_ID_UNSPECIFIED;
- private int mCurrentCategoryPageId = 0;
-
- public EmojiCategory(final SharedPreferences prefs, final Resources res,
- final KeyboardLayoutSet layoutSet) {
- mPrefs = prefs;
- mRes = res;
- mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
- mLayoutSet = layoutSet;
- for (int i = 0; i < sCategoryName.length; ++i) {
- mCategoryNameToIdMap.put(sCategoryName[i], i);
- }
- addShownCategoryId(CATEGORY_ID_RECENTS);
- if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
- || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
- addShownCategoryId(CATEGORY_ID_PEOPLE);
- addShownCategoryId(CATEGORY_ID_OBJECTS);
- addShownCategoryId(CATEGORY_ID_NATURE);
- addShownCategoryId(CATEGORY_ID_PLACES);
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_PEOPLE);
- } else {
- mCurrentCategoryId =
- Settings.readLastShownEmojiCategoryId(mPrefs, CATEGORY_ID_SYMBOLS);
- }
- addShownCategoryId(CATEGORY_ID_SYMBOLS);
- addShownCategoryId(CATEGORY_ID_EMOTICONS);
- getKeyboard(CATEGORY_ID_RECENTS, 0 /* cagetoryPageId */)
- .loadRecentKeys(mCategoryKeyboardMap.values());
- }
-
- private void addShownCategoryId(final int categoryId) {
- // Load a keyboard of categoryId
- getKeyboard(categoryId, 0 /* cagetoryPageId */);
- final CategoryProperties properties =
- new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
- mShownCategories.add(properties);
- }
-
- public String getCategoryName(final int categoryId, final int categoryPageId) {
- return sCategoryName[categoryId] + "-" + categoryPageId;
- }
-
- public int getCategoryId(final String name) {
- final String[] strings = name.split("-");
- return mCategoryNameToIdMap.get(strings[0]);
- }
-
- public int getCategoryIcon(final int categoryId) {
- return sCategoryIcon[categoryId];
- }
-
- public String getCategoryLabel(final int categoryId) {
- return sCategoryLabel[categoryId];
- }
-
- public String getAccessibilityDescription(final int categoryId) {
- return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
- }
-
- public ArrayList<CategoryProperties> getShownCategories() {
- return mShownCategories;
- }
-
- public int getCurrentCategoryId() {
- return mCurrentCategoryId;
- }
-
- public int getCurrentCategoryPageSize() {
- return getCategoryPageSize(mCurrentCategoryId);
- }
-
- public int getCategoryPageSize(final int categoryId) {
- for (final CategoryProperties prop : mShownCategories) {
- if (prop.mCategoryId == categoryId) {
- return prop.mPageCount;
- }
- }
- Log.w(TAG, "Invalid category id: " + categoryId);
- // Should not reach here.
- return 0;
- }
-
- public void setCurrentCategoryId(final int categoryId) {
- mCurrentCategoryId = categoryId;
- Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
- }
-
- public void setCurrentCategoryPageId(final int id) {
- mCurrentCategoryPageId = id;
- }
-
- public int getCurrentCategoryPageId() {
- return mCurrentCategoryPageId;
- }
-
- public void saveLastTypedCategoryPage() {
- Settings.writeLastTypedEmojiCategoryPageId(
- mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
- }
-
- public boolean isInRecentTab() {
- return mCurrentCategoryId == CATEGORY_ID_RECENTS;
- }
-
- public int getTabIdFromCategoryId(final int categoryId) {
- for (int i = 0; i < mShownCategories.size(); ++i) {
- if (mShownCategories.get(i).mCategoryId == categoryId) {
- return i;
- }
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- // Returns the view pager's page position for the categoryId
- public int getPageIdFromCategoryId(final int categoryId) {
- final int lastSavedCategoryPageId =
- Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
- int sum = 0;
- for (int i = 0; i < mShownCategories.size(); ++i) {
- final CategoryProperties props = mShownCategories.get(i);
- if (props.mCategoryId == categoryId) {
- return sum + lastSavedCategoryPageId;
- }
- sum += props.mPageCount;
- }
- Log.w(TAG, "categoryId not found: " + categoryId);
- return 0;
- }
-
- public int getRecentTabId() {
- return getTabIdFromCategoryId(CATEGORY_ID_RECENTS);
- }
-
- private int getCategoryPageCount(final int categoryId) {
- final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
- return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
- }
-
- // Returns a pair of the category id and the category page id from the view pager's page
- // position. The category page id is numbered in each category. And the view page position
- // is the position of the current shown page in the view pager which contains all pages of
- // all categories.
- public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(final int position) {
- int sum = 0;
- for (final CategoryProperties properties : mShownCategories) {
- final int temp = sum;
- sum += properties.mPageCount;
- if (sum > position) {
- return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
- }
- }
- return null;
- }
-
- // Returns a keyboard from the view pager's page position.
- public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
- final Pair<Integer, Integer> categoryAndId =
- getCategoryIdAndPageIdFromPagePosition(position);
- if (categoryAndId != null) {
- return getKeyboard(categoryAndId.first, categoryAndId.second);
- }
- return null;
- }
-
- private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) {
- return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id;
- }
-
- public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) {
- synchronized (mCategoryKeyboardMap) {
- final Long categotyKeyboardMapKey = getCategoryKeyboardMapKey(categoryId, id);
- if (mCategoryKeyboardMap.containsKey(categotyKeyboardMapKey)) {
- return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
- }
-
- if (categoryId == CATEGORY_ID_RECENTS) {
- final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
- mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
- mMaxPageKeyCount, categoryId);
- mCategoryKeyboardMap.put(categotyKeyboardMapKey, kbd);
- return kbd;
- }
-
- final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
- final Key[][] sortedKeys = sortKeysIntoPages(
- keyboard.getSortedKeys(), mMaxPageKeyCount);
- for (int pageId = 0; pageId < sortedKeys.length; ++pageId) {
- final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
- mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
- mMaxPageKeyCount, categoryId);
- for (final Key emojiKey : sortedKeys[pageId]) {
- if (emojiKey == null) {
- break;
- }
- tempKeyboard.addKeyLast(emojiKey);
- }
- mCategoryKeyboardMap.put(
- getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
- }
- return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
- }
- }
-
- public int getTotalPageCountOfAllCategories() {
- int sum = 0;
- for (CategoryProperties properties : mShownCategories) {
- sum += properties.mPageCount;
- }
- return sum;
- }
-
- private static Comparator<Key> EMOJI_KEY_COMPARATOR = new Comparator<Key>() {
- @Override
- public int compare(final Key lhs, final Key rhs) {
- final Rect lHitBox = lhs.getHitBox();
- final Rect rHitBox = rhs.getHitBox();
- if (lHitBox.top < rHitBox.top) {
- return -1;
- } else if (lHitBox.top > rHitBox.top) {
- return 1;
- }
- if (lHitBox.left < rHitBox.left) {
- return -1;
- } else if (lHitBox.left > rHitBox.left) {
- return 1;
- }
- if (lhs.getCode() == rhs.getCode()) {
- return 0;
- }
- return lhs.getCode() < rhs.getCode() ? -1 : 1;
- }
- };
-
- private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
- final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
- Collections.sort(keys, EMOJI_KEY_COMPARATOR);
- final int pageCount = (keys.size() - 1) / maxPageCount + 1;
- final Key[][] retval = new Key[pageCount][maxPageCount];
- for (int i = 0; i < keys.size(); ++i) {
- retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
- }
- return retval;
- }
- }
-
private final EmojiCategory mEmojiCategory;
public EmojiPalettesView(final Context context, final AttributeSet attrs) {
@@ -481,7 +155,8 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
protected void onFinishInflate() {
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
mTabHost.setup();
- for (final CategoryProperties properties : mEmojiCategory.getShownCategories()) {
+ for (final EmojiCategory.CategoryProperties properties
+ : mEmojiCategory.getShownCategories()) {
addTab(mTabHost, properties.mCategoryId);
}
mTabHost.setOnTabChangedListener(this);
@@ -675,9 +350,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
public void startEmojiPalettes(final String switchToAlphaLabel,
final KeyVisualAttributes keyVisualAttr) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "allocate emoji palettes memory " + mCurrentPagerPosition);
- }
final KeyDrawParams params = new KeyDrawParams();
params.updateParams(mEmojiLayoutParams.getActionBarHeight(), keyVisualAttr);
setupAlphabetKey(mAlphabetKeyLeft, switchToAlphaLabel, params);
@@ -687,9 +359,6 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
public void stopEmojiPalettes() {
- if (DEBUG_PAGER) {
- Log.d(TAG, "deallocate emoji palettes memory");
- }
mEmojiPalettesAdapter.flushPendingRecentKeys();
mEmojiPager.setAdapter(null);
}
@@ -714,7 +383,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
return;
}
- if (oldCategoryId == CATEGORY_ID_RECENTS) {
+ if (oldCategoryId == EmojiCategory.ID_RECENTS) {
// 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.
@@ -733,124 +402,11 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
}
- private static class EmojiPalettesAdapter extends PagerAdapter {
- private final EmojiPageKeyboardView.OnKeyEventListener mListener;
- private final DynamicGridKeyboard mRecentsKeyboard;
- private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
- CollectionUtils.newSparseArray();
- private final EmojiCategory mEmojiCategory;
- private int mActivePosition = 0;
-
- public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
- final EmojiPageKeyboardView.OnKeyEventListener listener) {
- mEmojiCategory = emojiCategory;
- mListener = listener;
- mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_ID_RECENTS, 0);
- }
-
- public void flushPendingRecentKeys() {
- mRecentsKeyboard.flushPendingRecentKeys();
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void addRecentKey(final Key key) {
- if (mEmojiCategory.isInRecentTab()) {
- mRecentsKeyboard.addPendingKey(key);
- return;
- }
- mRecentsKeyboard.addKeyFirst(key);
- final KeyboardView recentKeyboardView =
- mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
- if (recentKeyboardView != null) {
- recentKeyboardView.invalidateAllKeys();
- }
- }
-
- public void onPageScrolled() {
- // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
- // canceled.
- final EmojiPageKeyboardView currentKeyboardView =
- mActiveKeyboardViews.get(mActivePosition);
- if (currentKeyboardView != null) {
- currentKeyboardView.releaseCurrentKey();
- }
- }
-
- @Override
- public int getCount() {
- return mEmojiCategory.getTotalPageCountOfAllCategories();
- }
-
- @Override
- public void setPrimaryItem(final ViewGroup container, final int position,
- final Object object) {
- if (mActivePosition == position) {
- return;
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
- if (oldKeyboardView != null) {
- oldKeyboardView.releaseCurrentKey();
- oldKeyboardView.deallocateMemory();
- }
- mActivePosition = position;
- }
-
- @Override
- public Object instantiateItem(final ViewGroup container, final int position) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "instantiate item: " + position);
- }
- final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
- if (oldKeyboardView != null) {
- oldKeyboardView.deallocateMemory();
- // This may be redundant but wanted to be safer..
- mActiveKeyboardViews.remove(position);
- }
- final Keyboard keyboard =
- mEmojiCategory.getKeyboardFromPagePosition(position);
- final LayoutInflater inflater = LayoutInflater.from(container.getContext());
- final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
- R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
- keyboardView.setKeyboard(keyboard);
- keyboardView.setOnKeyEventListener(mListener);
- container.addView(keyboardView);
- mActiveKeyboardViews.put(position, keyboardView);
- return keyboardView;
- }
-
- @Override
- public boolean isViewFromObject(final View view, final Object object) {
- return view == object;
- }
-
- @Override
- public void destroyItem(final ViewGroup container, final int position,
- final Object object) {
- if (DEBUG_PAGER) {
- Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
- }
- final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
- if (keyboardView != null) {
- keyboardView.deallocateMemory();
- mActiveKeyboardViews.remove(position);
- }
- if (object instanceof View) {
- container.removeView((View)object);
- } else {
- Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
- }
- }
- }
-
private static class DeleteKeyOnTouchListener implements OnTouchListener {
- private static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
- private final int mDeleteKeyPressedBackgroundColor;
- private final long mKeyRepeatStartTimeout;
- private final long mKeyRepeatInterval;
+ static final long MAX_REPEAT_COUNT_TIME = TimeUnit.SECONDS.toMillis(30);
+ final int mDeleteKeyPressedBackgroundColor;
+ final long mKeyRepeatStartTimeout;
+ final long mKeyRepeatInterval;
public DeleteKeyOnTouchListener(Context context) {
final Resources res = context.getResources();
@@ -953,7 +509,7 @@ public final class EmojiPalettesView extends LinearLayout implements OnTabChange
}
// Called by {@link #mTimer} in the UI thread as an auto key-repeat signal.
- private void onKeyRepeat() {
+ void onKeyRepeat() {
switch (mState) {
case KEY_REPEAT_STATE_INITIALIZED:
// Basically this should not happen.
diff --git a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
index 67a222732..a4879b852 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java
@@ -20,7 +20,6 @@ import android.content.SharedPreferences;
import android.text.TextUtils;
import android.util.Log;
-import com.android.inputmethod.keyboard.EmojiPalettesView;
import com.android.inputmethod.keyboard.Key;
import com.android.inputmethod.keyboard.Keyboard;
import com.android.inputmethod.latin.settings.Settings;
@@ -36,6 +35,7 @@ import java.util.List;
/**
* This is a Keyboard class where you can add keys dynamically shown in a grid layout
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
public class DynamicGridKeyboard extends Keyboard {
private static final String TAG = DynamicGridKeyboard.class.getSimpleName();
private static final int TEMPLATE_KEY_CODE_0 = 0x30;
@@ -62,7 +62,7 @@ public class DynamicGridKeyboard extends Keyboard {
mVerticalStep = key0.getHeight() + mVerticalGap;
mColumnsNum = mBaseWidth / mHorizontalStep;
mMaxKeyCount = maxKeyCount;
- mIsRecents = categoryId == EmojiPalettesView.CATEGORY_ID_RECENTS;
+ mIsRecents = categoryId == EmojiCategory.ID_RECENTS;
mPrefs = prefs;
}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java
new file mode 100644
index 000000000..10bd621e5
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiCategory.java
@@ -0,0 +1,359 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.content.SharedPreferences;
+import android.content.res.Resources;
+import android.graphics.Rect;
+import android.os.Build;
+import android.util.Log;
+import android.util.Pair;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardId;
+import com.android.inputmethod.keyboard.KeyboardLayoutSet;
+import com.android.inputmethod.latin.Constants;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.settings.Settings;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+
+// TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiCategory {
+ private final String TAG = EmojiCategory.class.getSimpleName();
+
+ private static final int ID_UNSPECIFIED = -1;
+ public static final int ID_RECENTS = 0;
+ private static final int ID_PEOPLE = 1;
+ private static final int ID_OBJECTS = 2;
+ private static final int ID_NATURE = 3;
+ private static final int ID_PLACES = 4;
+ private static final int ID_SYMBOLS = 5;
+ private static final int ID_EMOTICONS = 6;
+
+ public final class CategoryProperties {
+ public final int mCategoryId;
+ public final int mPageCount;
+ public CategoryProperties(final int categoryId, final int pageCount) {
+ mCategoryId = categoryId;
+ mPageCount = pageCount;
+ }
+ }
+
+ private static final String[] sCategoryName = {
+ "recents",
+ "people",
+ "objects",
+ "nature",
+ "places",
+ "symbols",
+ "emoticons" };
+
+ private static final int[] sCategoryIcon = {
+ R.drawable.ic_emoji_recent_light,
+ R.drawable.ic_emoji_people_light,
+ R.drawable.ic_emoji_objects_light,
+ R.drawable.ic_emoji_nature_light,
+ R.drawable.ic_emoji_places_light,
+ R.drawable.ic_emoji_symbols_light,
+ 0 };
+
+ private static final String[] sCategoryLabel =
+ { null, null, null, null, null, null, ":-)" };
+
+ private static final int[] sAccessibilityDescriptionResourceIdsForCategories = {
+ R.string.spoken_descrption_emoji_category_recents,
+ R.string.spoken_descrption_emoji_category_people,
+ R.string.spoken_descrption_emoji_category_objects,
+ R.string.spoken_descrption_emoji_category_nature,
+ R.string.spoken_descrption_emoji_category_places,
+ R.string.spoken_descrption_emoji_category_symbols,
+ R.string.spoken_descrption_emoji_category_emoticons };
+
+ private static final int[] sCategoryElementId = {
+ KeyboardId.ELEMENT_EMOJI_RECENTS,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY1,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY2,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY3,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY4,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY5,
+ KeyboardId.ELEMENT_EMOJI_CATEGORY6 };
+
+ private final SharedPreferences mPrefs;
+ private final Resources mRes;
+ private final int mMaxPageKeyCount;
+ private final KeyboardLayoutSet mLayoutSet;
+ private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap();
+ private final ArrayList<CategoryProperties> mShownCategories =
+ CollectionUtils.newArrayList();
+ private final ConcurrentHashMap<Long, DynamicGridKeyboard>
+ mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
+
+ private int mCurrentCategoryId = EmojiCategory.ID_UNSPECIFIED;
+ private int mCurrentCategoryPageId = 0;
+
+ public EmojiCategory(final SharedPreferences prefs, final Resources res,
+ final KeyboardLayoutSet layoutSet) {
+ mPrefs = prefs;
+ mRes = res;
+ mMaxPageKeyCount = res.getInteger(R.integer.config_emoji_keyboard_max_page_key_count);
+ mLayoutSet = layoutSet;
+ for (int i = 0; i < sCategoryName.length; ++i) {
+ mCategoryNameToIdMap.put(sCategoryName[i], i);
+ }
+ addShownCategoryId(EmojiCategory.ID_RECENTS);
+ if (Build.VERSION.SDK_INT > Build.VERSION_CODES.JELLY_BEAN_MR2
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KeyLimePie")
+ || android.os.Build.VERSION.CODENAME.equalsIgnoreCase("KitKat")) {
+ addShownCategoryId(EmojiCategory.ID_PEOPLE);
+ addShownCategoryId(EmojiCategory.ID_OBJECTS);
+ addShownCategoryId(EmojiCategory.ID_NATURE);
+ addShownCategoryId(EmojiCategory.ID_PLACES);
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_PEOPLE);
+ } else {
+ mCurrentCategoryId =
+ Settings.readLastShownEmojiCategoryId(mPrefs, EmojiCategory.ID_SYMBOLS);
+ }
+ addShownCategoryId(EmojiCategory.ID_SYMBOLS);
+ addShownCategoryId(EmojiCategory.ID_EMOTICONS);
+ getKeyboard(EmojiCategory.ID_RECENTS, 0 /* cagetoryPageId */)
+ .loadRecentKeys(mCategoryKeyboardMap.values());
+ }
+
+ private void addShownCategoryId(final int categoryId) {
+ // Load a keyboard of categoryId
+ getKeyboard(categoryId, 0 /* cagetoryPageId */);
+ final CategoryProperties properties =
+ new CategoryProperties(categoryId, getCategoryPageCount(categoryId));
+ mShownCategories.add(properties);
+ }
+
+ public String getCategoryName(final int categoryId, final int categoryPageId) {
+ return sCategoryName[categoryId] + "-" + categoryPageId;
+ }
+
+ public int getCategoryId(final String name) {
+ final String[] strings = name.split("-");
+ return mCategoryNameToIdMap.get(strings[0]);
+ }
+
+ public int getCategoryIcon(final int categoryId) {
+ return sCategoryIcon[categoryId];
+ }
+
+ public String getCategoryLabel(final int categoryId) {
+ return sCategoryLabel[categoryId];
+ }
+
+ public String getAccessibilityDescription(final int categoryId) {
+ return mRes.getString(sAccessibilityDescriptionResourceIdsForCategories[categoryId]);
+ }
+
+ public ArrayList<CategoryProperties> getShownCategories() {
+ return mShownCategories;
+ }
+
+ public int getCurrentCategoryId() {
+ return mCurrentCategoryId;
+ }
+
+ public int getCurrentCategoryPageSize() {
+ return getCategoryPageSize(mCurrentCategoryId);
+ }
+
+ public int getCategoryPageSize(final int categoryId) {
+ for (final CategoryProperties prop : mShownCategories) {
+ if (prop.mCategoryId == categoryId) {
+ return prop.mPageCount;
+ }
+ }
+ Log.w(TAG, "Invalid category id: " + categoryId);
+ // Should not reach here.
+ return 0;
+ }
+
+ public void setCurrentCategoryId(final int categoryId) {
+ mCurrentCategoryId = categoryId;
+ Settings.writeLastShownEmojiCategoryId(mPrefs, categoryId);
+ }
+
+ public void setCurrentCategoryPageId(final int id) {
+ mCurrentCategoryPageId = id;
+ }
+
+ public int getCurrentCategoryPageId() {
+ return mCurrentCategoryPageId;
+ }
+
+ public void saveLastTypedCategoryPage() {
+ Settings.writeLastTypedEmojiCategoryPageId(
+ mPrefs, mCurrentCategoryId, mCurrentCategoryPageId);
+ }
+
+ public boolean isInRecentTab() {
+ return mCurrentCategoryId == EmojiCategory.ID_RECENTS;
+ }
+
+ public int getTabIdFromCategoryId(final int categoryId) {
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ if (mShownCategories.get(i).mCategoryId == categoryId) {
+ return i;
+ }
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ // Returns the view pager's page position for the categoryId
+ public int getPageIdFromCategoryId(final int categoryId) {
+ final int lastSavedCategoryPageId =
+ Settings.readLastTypedEmojiCategoryPageId(mPrefs, categoryId);
+ int sum = 0;
+ for (int i = 0; i < mShownCategories.size(); ++i) {
+ final CategoryProperties props = mShownCategories.get(i);
+ if (props.mCategoryId == categoryId) {
+ return sum + lastSavedCategoryPageId;
+ }
+ sum += props.mPageCount;
+ }
+ Log.w(TAG, "categoryId not found: " + categoryId);
+ return 0;
+ }
+
+ public int getRecentTabId() {
+ return getTabIdFromCategoryId(EmojiCategory.ID_RECENTS);
+ }
+
+ private int getCategoryPageCount(final int categoryId) {
+ final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
+ return (keyboard.getSortedKeys().size() - 1) / mMaxPageKeyCount + 1;
+ }
+
+ // Returns a pair of the category id and the category page id from the view pager's page
+ // position. The category page id is numbered in each category. And the view page position
+ // is the position of the current shown page in the view pager which contains all pages of
+ // all categories.
+ public Pair<Integer, Integer> getCategoryIdAndPageIdFromPagePosition(final int position) {
+ int sum = 0;
+ for (final CategoryProperties properties : mShownCategories) {
+ final int temp = sum;
+ sum += properties.mPageCount;
+ if (sum > position) {
+ return new Pair<Integer, Integer>(properties.mCategoryId, position - temp);
+ }
+ }
+ return null;
+ }
+
+ // Returns a keyboard from the view pager's page position.
+ public DynamicGridKeyboard getKeyboardFromPagePosition(final int position) {
+ final Pair<Integer, Integer> categoryAndId =
+ getCategoryIdAndPageIdFromPagePosition(position);
+ if (categoryAndId != null) {
+ return getKeyboard(categoryAndId.first, categoryAndId.second);
+ }
+ return null;
+ }
+
+ private static final Long getCategoryKeyboardMapKey(final int categoryId, final int id) {
+ return (((long) categoryId) << Constants.MAX_INT_BIT_COUNT) | id;
+ }
+
+ public DynamicGridKeyboard getKeyboard(final int categoryId, final int id) {
+ synchronized (mCategoryKeyboardMap) {
+ final Long categotyKeyboardMapKey = getCategoryKeyboardMapKey(categoryId, id);
+ if (mCategoryKeyboardMap.containsKey(categotyKeyboardMapKey)) {
+ return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
+ }
+
+ if (categoryId == EmojiCategory.ID_RECENTS) {
+ final DynamicGridKeyboard kbd = new DynamicGridKeyboard(mPrefs,
+ mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
+ mMaxPageKeyCount, categoryId);
+ mCategoryKeyboardMap.put(categotyKeyboardMapKey, kbd);
+ return kbd;
+ }
+
+ final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[categoryId]);
+ final Key[][] sortedKeys = sortKeysIntoPages(
+ keyboard.getSortedKeys(), mMaxPageKeyCount);
+ for (int pageId = 0; pageId < sortedKeys.length; ++pageId) {
+ final DynamicGridKeyboard tempKeyboard = new DynamicGridKeyboard(mPrefs,
+ mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
+ mMaxPageKeyCount, categoryId);
+ for (final Key emojiKey : sortedKeys[pageId]) {
+ if (emojiKey == null) {
+ break;
+ }
+ tempKeyboard.addKeyLast(emojiKey);
+ }
+ mCategoryKeyboardMap.put(
+ getCategoryKeyboardMapKey(categoryId, pageId), tempKeyboard);
+ }
+ return mCategoryKeyboardMap.get(categotyKeyboardMapKey);
+ }
+ }
+
+ public int getTotalPageCountOfAllCategories() {
+ int sum = 0;
+ for (CategoryProperties properties : mShownCategories) {
+ sum += properties.mPageCount;
+ }
+ return sum;
+ }
+
+ private static Comparator<Key> EMOJI_KEY_COMPARATOR = new Comparator<Key>() {
+ @Override
+ public int compare(final Key lhs, final Key rhs) {
+ final Rect lHitBox = lhs.getHitBox();
+ final Rect rHitBox = rhs.getHitBox();
+ if (lHitBox.top < rHitBox.top) {
+ return -1;
+ } else if (lHitBox.top > rHitBox.top) {
+ return 1;
+ }
+ if (lHitBox.left < rHitBox.left) {
+ return -1;
+ } else if (lHitBox.left > rHitBox.left) {
+ return 1;
+ }
+ if (lhs.getCode() == rhs.getCode()) {
+ return 0;
+ }
+ return lhs.getCode() < rhs.getCode() ? -1 : 1;
+ }
+ };
+
+ private static Key[][] sortKeysIntoPages(final List<Key> inKeys, final int maxPageCount) {
+ final ArrayList<Key> keys = CollectionUtils.newArrayList(inKeys);
+ Collections.sort(keys, EMOJI_KEY_COMPARATOR);
+ final int pageCount = (keys.size() - 1) / maxPageCount + 1;
+ final Key[][] retval = new Key[pageCount][maxPageCount];
+ for (int i = 0; i < keys.size(); ++i) {
+ retval[i / maxPageCount][i % maxPageCount] = keys.get(i);
+ }
+ return retval;
+ }
+}
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
index d57ea5a94..78af66b9a 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiLayoutParams.java
@@ -24,7 +24,8 @@ import android.support.v4.view.ViewPager;
import android.widget.ImageView;
import android.widget.LinearLayout;
-public class EmojiLayoutParams {
+//TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiLayoutParams {
private static final int DEFAULT_KEYBOARD_ROWS = 4;
public final int mEmojiPagerHeight;
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
index e175a051e..2f67d194e 100644
--- a/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPageKeyboardView.java
@@ -33,6 +33,7 @@ import com.android.inputmethod.latin.R;
* This is an extended {@link KeyboardView} class that hosts an emoji page keyboard.
* Multi-touch unsupported. No {@link PointerTracker}s. No gesture support.
*/
+// TODO: Move this class to com.android.inputmethod.emoji package.
// TODO: Implement key popup preview.
public final class EmojiPageKeyboardView extends KeyboardView implements
GestureDetector.OnGestureListener {
diff --git a/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java b/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java
new file mode 100644
index 000000000..a44d13407
--- /dev/null
+++ b/java/src/com/android/inputmethod/keyboard/internal/EmojiPalettesAdapter.java
@@ -0,0 +1,147 @@
+/*
+ * Copyright (C) 2014 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.
+ */
+
+package com.android.inputmethod.keyboard.internal;
+
+import android.support.v4.view.PagerAdapter;
+import android.util.Log;
+import android.util.SparseArray;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import com.android.inputmethod.keyboard.Key;
+import com.android.inputmethod.keyboard.Keyboard;
+import com.android.inputmethod.keyboard.KeyboardView;
+import com.android.inputmethod.latin.R;
+import com.android.inputmethod.latin.utils.CollectionUtils;
+
+// TODO: Move this class to com.android.inputmethod.emoji package.
+public final class EmojiPalettesAdapter extends PagerAdapter {
+ private static final String TAG = EmojiPalettesAdapter.class.getSimpleName();
+ private static final boolean DEBUG_PAGER = false;
+
+ private final EmojiPageKeyboardView.OnKeyEventListener mListener;
+ private final DynamicGridKeyboard mRecentsKeyboard;
+ private final SparseArray<EmojiPageKeyboardView> mActiveKeyboardViews =
+ CollectionUtils.newSparseArray();
+ private final EmojiCategory mEmojiCategory;
+ private int mActivePosition = 0;
+
+ public EmojiPalettesAdapter(final EmojiCategory emojiCategory,
+ final EmojiPageKeyboardView.OnKeyEventListener listener) {
+ mEmojiCategory = emojiCategory;
+ mListener = listener;
+ mRecentsKeyboard = mEmojiCategory.getKeyboard(EmojiCategory.ID_RECENTS, 0);
+ }
+
+ public void flushPendingRecentKeys() {
+ mRecentsKeyboard.flushPendingRecentKeys();
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void addRecentKey(final Key key) {
+ if (mEmojiCategory.isInRecentTab()) {
+ mRecentsKeyboard.addPendingKey(key);
+ return;
+ }
+ mRecentsKeyboard.addKeyFirst(key);
+ final KeyboardView recentKeyboardView =
+ mActiveKeyboardViews.get(mEmojiCategory.getRecentTabId());
+ if (recentKeyboardView != null) {
+ recentKeyboardView.invalidateAllKeys();
+ }
+ }
+
+ public void onPageScrolled() {
+ // Make sure the delayed key-down event (highlight effect and haptic feedback) will be
+ // canceled.
+ final EmojiPageKeyboardView currentKeyboardView =
+ mActiveKeyboardViews.get(mActivePosition);
+ if (currentKeyboardView != null) {
+ currentKeyboardView.releaseCurrentKey();
+ }
+ }
+
+ @Override
+ public int getCount() {
+ return mEmojiCategory.getTotalPageCountOfAllCategories();
+ }
+
+ @Override
+ public void setPrimaryItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (mActivePosition == position) {
+ return;
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(mActivePosition);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.releaseCurrentKey();
+ oldKeyboardView.deallocateMemory();
+ }
+ mActivePosition = position;
+ }
+
+ @Override
+ public Object instantiateItem(final ViewGroup container, final int position) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "instantiate item: " + position);
+ }
+ final EmojiPageKeyboardView oldKeyboardView = mActiveKeyboardViews.get(position);
+ if (oldKeyboardView != null) {
+ oldKeyboardView.deallocateMemory();
+ // This may be redundant but wanted to be safer..
+ mActiveKeyboardViews.remove(position);
+ }
+ final Keyboard keyboard =
+ mEmojiCategory.getKeyboardFromPagePosition(position);
+ final LayoutInflater inflater = LayoutInflater.from(container.getContext());
+ final EmojiPageKeyboardView keyboardView = (EmojiPageKeyboardView)inflater.inflate(
+ R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
+ keyboardView.setKeyboard(keyboard);
+ keyboardView.setOnKeyEventListener(mListener);
+ container.addView(keyboardView);
+ mActiveKeyboardViews.put(position, keyboardView);
+ return keyboardView;
+ }
+
+ @Override
+ public boolean isViewFromObject(final View view, final Object object) {
+ return view == object;
+ }
+
+ @Override
+ public void destroyItem(final ViewGroup container, final int position,
+ final Object object) {
+ if (DEBUG_PAGER) {
+ Log.d(TAG, "destroy item: " + position + ", " + object.getClass().getSimpleName());
+ }
+ final EmojiPageKeyboardView keyboardView = mActiveKeyboardViews.get(position);
+ if (keyboardView != null) {
+ keyboardView.deallocateMemory();
+ mActiveKeyboardViews.remove(position);
+ }
+ if (object instanceof View) {
+ container.removeView((View)object);
+ } else {
+ Log.w(TAG, "Warning!!! Emoji palette may be leaking. " + object);
+ }
+ }
+}