Loading java/src/com/android/inputmethod/keyboard/EmojiKeyboardView.java +92 −19 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.TypedArray; import android.graphics.Rect; import android.os.Build; import android.os.Build; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager; Loading @@ -37,7 +38,9 @@ import android.widget.TabHost; import android.widget.TabHost.OnTabChangeListener; import android.widget.TabHost.OnTabChangeListener; import android.widget.TextView; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.CodesArrayParser; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants; Loading @@ -47,7 +50,10 @@ import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; /** /** * View class to implement Emoji keyboards. * View class to implement Emoji keyboards. Loading Loading @@ -75,8 +81,6 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; private static class EmojiCategory { private int mCurrentCategory = CATEGORY_UNSPECIFIED; private static final int CATEGORY_UNSPECIFIED = -1; private static final int CATEGORY_UNSPECIFIED = -1; private static final int CATEGORY_RECENTS = 0; private static final int CATEGORY_RECENTS = 0; private static final int CATEGORY_PEOPLE = 1; private static final int CATEGORY_PEOPLE = 1; Loading @@ -85,6 +89,9 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange private static final int CATEGORY_PLACES = 4; private static final int CATEGORY_PLACES = 4; private static final int CATEGORY_SYMBOLS = 5; private static final int CATEGORY_SYMBOLS = 5; private static final int CATEGORY_EMOTICONS = 6; private static final int CATEGORY_EMOTICONS = 6; private static class EmojiCategory { private static final int DEFAULT_MAX_ROW_SIZE = 3; private static final String[] sCategoryName = { private static final String[] sCategoryName = { "recents", "recents", "people", "people", Loading @@ -111,10 +118,18 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange KeyboardId.ELEMENT_EMOJI_CATEGORY4, KeyboardId.ELEMENT_EMOJI_CATEGORY4, KeyboardId.ELEMENT_EMOJI_CATEGORY5, KeyboardId.ELEMENT_EMOJI_CATEGORY5, KeyboardId.ELEMENT_EMOJI_CATEGORY6, }; KeyboardId.ELEMENT_EMOJI_CATEGORY6, }; private Resources mRes; private final KeyboardLayoutSet mLayoutSet; private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap(); private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap(); private final ArrayList<Integer> mShownCategories = new ArrayList<Integer>(); private final ArrayList<Integer> mShownCategories = new ArrayList<Integer>(); private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>(); public EmojiCategory() { private int mCurrentCategory = CATEGORY_UNSPECIFIED; public EmojiCategory(final Resources res, final KeyboardLayoutSet layoutSet) { mRes = res; mLayoutSet = layoutSet; for (int i = 0; i < sCategoryName.length; ++i) { for (int i = 0; i < sCategoryName.length; ++i) { mCategoryNameToIdMap.put(sCategoryName[i], i); mCategoryNameToIdMap.put(sCategoryName[i], i); } } Loading Loading @@ -185,12 +200,71 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange return mShownCategories.get(tabId); return mShownCategories.get(tabId); } } public int getElementIdFromTabId(int tabId) { public DynamicGridKeyboard getKeyboard(int category, int id) { return sCategoryElementId[getCategoryFromTabId(tabId)]; synchronized(mCategoryKeyboardMap) { final long key = (((long) category) << 32) | id; final DynamicGridKeyboard kbd; if (!mCategoryKeyboardMap.containsKey(key)) { if (category != CATEGORY_RECENTS) { kbd = new DynamicGridKeyboard( mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), DEFAULT_MAX_ROW_SIZE); final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[category]); // TODO: Calculate maxPageCount dynamically final Key[][] sortedKeys = sortKeys(keyboard.getKeys(), 21); for (Key emojiKey : sortedKeys[0]) { if (emojiKey == null) { break; } kbd.addKeyLast(emojiKey); } } else { kbd = new DynamicGridKeyboard( mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), DEFAULT_MAX_ROW_SIZE); } mCategoryKeyboardMap.put(key, kbd); } else { kbd = mCategoryKeyboardMap.get(key); } return kbd; } } private Key[][] sortKeys(Key[] inKeys, int maxPageCount) { Key[] keys = Arrays.copyOf(inKeys, inKeys.length); Arrays.sort(keys, 0, keys.length, new Comparator<Key>() { @Override public int compare(Key lhs, 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; } }); final int pageCount = (keys.length - 1) / maxPageCount + 1; final Key[][] retval = new Key[pageCount][maxPageCount]; for (int i = 0; i < keys.length; ++i) { retval[i / maxPageCount][i % maxPageCount] = keys[i]; } return retval; } } } } private final EmojiCategory mEmojiCategory = new EmojiCategory(); private final EmojiCategory mEmojiCategory; public EmojiKeyboardView(final Context context, final AttributeSet attrs) { public EmojiKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.emojiKeyboardViewStyle); this(context, attrs, R.attr.emojiKeyboardViewStyle); Loading Loading @@ -219,6 +293,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange + res.getDimensionPixelSize(R.dimen.suggestions_strip_height)); + res.getDimensionPixelSize(R.dimen.suggestions_strip_height)); builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */); builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */); mLayoutSet = builder.build(); mLayoutSet = builder.build(); mEmojiCategory = new EmojiCategory(context.getResources(), builder.build()); // TODO: Save/restore recent keys from/to preferences. // TODO: Save/restore recent keys from/to preferences. } } Loading Loading @@ -388,15 +463,14 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange mEmojiCategory = emojiCategory; mEmojiCategory = emojiCategory; mListener = listener; mListener = listener; mLayoutSet = layoutSet; mLayoutSet = layoutSet; mRecentsKeyboard = new DynamicGridKeyboard( mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_RECENTS, 0); layoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS)); } } public void addRecentKey(final Key key) { public void addRecentKey(final Key key) { if (mEmojiCategory.isInRecentTab()) { if (mEmojiCategory.isInRecentTab()) { return; return; } } mRecentsKeyboard.addRecentKey(key); mRecentsKeyboard.addKeyFirst(key); final KeyboardView recentKeyboardView = final KeyboardView recentKeyboardView = mActiveKeyboardView.get(mEmojiCategory.getRecentTabId()); mActiveKeyboardView.get(mEmojiCategory.getRecentTabId()); if (recentKeyboardView != null) { if (recentKeyboardView != null) { Loading Loading @@ -424,9 +498,8 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange @Override @Override public Object instantiateItem(final ViewGroup container, final int position) { public Object instantiateItem(final ViewGroup container, final int position) { final int elementId = mEmojiCategory.getElementIdFromTabId(position); final Keyboard keyboard = final Keyboard keyboard = (elementId == KeyboardId.ELEMENT_EMOJI_RECENTS) mEmojiCategory.getKeyboard(mEmojiCategory.getCategoryFromTabId(position), 0); ? mRecentsKeyboard : mLayoutSet.getKeyboard(elementId); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); final View view = inflater.inflate( final View view = inflater.inflate( R.layout.emoji_keyboard_page, container, false /* attachToRoot */); R.layout.emoji_keyboard_page, container, false /* attachToRoot */); Loading java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java +35 −30 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,6 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.ArrayDeque; import java.util.ArrayDeque; import java.util.Random; /** /** * This is a Keyboard class where you can add keys dynamically shown in a grid layout * This is a Keyboard class where you can add keys dynamically shown in a grid layout Loading @@ -37,12 +36,12 @@ public class DynamicGridKeyboard extends Keyboard { private final int mHorizontalStep; private final int mHorizontalStep; private final int mVerticalStep; private final int mVerticalStep; private final int mColumnsNum; private final int mColumnsNum; private final int mMaxRecentKeyCount; private final int mMaxKeyCount; private final ArrayDeque<RecentKey> mRecentKeys = CollectionUtils.newArrayDeque(); private final ArrayDeque<GridKey> mGridKeys = CollectionUtils.newArrayDeque(); private Key[] mCachedRecentKeys; private Key[] mCachedGridKeys; public DynamicGridKeyboard(final Keyboard templateKeyboard) { public DynamicGridKeyboard(final Keyboard templateKeyboard, final int maxRows) { super(templateKeyboard); super(templateKeyboard); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); Loading @@ -50,8 +49,7 @@ public class DynamicGridKeyboard extends Keyboard { mHorizontalStep = Math.abs(key1.getX() - key0.getX()); mHorizontalStep = Math.abs(key1.getX() - key0.getX()); mVerticalStep = key0.getHeight() + mVerticalGap; mVerticalStep = key0.getHeight() + mVerticalGap; mColumnsNum = mBaseWidth / mHorizontalStep; mColumnsNum = mBaseWidth / mHorizontalStep; final int rowsNum = mBaseHeight / mVerticalStep; mMaxKeyCount = mColumnsNum * maxRows; mMaxRecentKeyCount = mColumnsNum * rowsNum; } } private Key getTemplateKey(final int code) { private Key getTemplateKey(final int code) { Loading @@ -63,27 +61,34 @@ public class DynamicGridKeyboard extends Keyboard { throw new RuntimeException("Can't find template key: code=" + code); throw new RuntimeException("Can't find template key: code=" + code); } } private final Random random = new Random(); public void addKeyFirst(final Key usedKey) { addKey(usedKey, true); } public void addKeyLast(final Key usedKey) { addKey(usedKey, false); } public void addRecentKey(final Key usedKey) { private void addKey(final Key usedKey, final boolean addFirst) { synchronized (mRecentKeys) { synchronized (mGridKeys) { mCachedRecentKeys = null; mCachedGridKeys = null; final RecentKey key = (usedKey instanceof RecentKey) final GridKey key = new GridKey(usedKey); ? (RecentKey)usedKey : new RecentKey(usedKey); while (mGridKeys.remove(key)) { while (mRecentKeys.remove(key)) { // Remove duplicate keys. // Remove duplicate keys. } } mRecentKeys.addFirst(key); if (addFirst) { while (mRecentKeys.size() > mMaxRecentKeyCount) { mGridKeys.addFirst(key); mRecentKeys.removeLast(); } else { mGridKeys.addLast(key); } while (mGridKeys.size() > mMaxKeyCount) { mGridKeys.removeLast(); } } int index = 0; int index = 0; for (final RecentKey recentKey : mRecentKeys) { for (final GridKey gridKey : mGridKeys) { final int keyX = getKeyX(index); final int keyX = getKeyX(index); final int keyY = getKeyY(index); final int keyY = getKeyY(index); final int x = keyX+random.nextInt(recentKey.getWidth()); gridKey.updateCorrdinates(keyX, keyY); final int y = keyY+random.nextInt(recentKey.getHeight()); recentKey.updateCorrdinates(keyX, keyY); index++; index++; } } } } Loading @@ -101,26 +106,26 @@ public class DynamicGridKeyboard extends Keyboard { @Override @Override public Key[] getKeys() { public Key[] getKeys() { synchronized (mRecentKeys) { synchronized (mGridKeys) { if (mCachedRecentKeys != null) { if (mCachedGridKeys != null) { return mCachedRecentKeys; return mCachedGridKeys; } } mCachedRecentKeys = mRecentKeys.toArray(new Key[mRecentKeys.size()]); mCachedGridKeys = mGridKeys.toArray(new Key[mGridKeys.size()]); return mCachedRecentKeys; return mCachedGridKeys; } } } } @Override @Override public Key[] getNearestKeys(final int x, final int y) { public Key[] getNearestKeys(final int x, final int y) { // TODO: Calculate the nearest key index in mRecentKeys from x and y. // TODO: Calculate the nearest key index in mGridKeys from x and y. return getKeys(); return getKeys(); } } static final class RecentKey extends Key { static final class GridKey extends Key { private int mCurrentX; private int mCurrentX; private int mCurrentY; private int mCurrentY; public RecentKey(final Key originalKey) { public GridKey(final Key originalKey) { super(originalKey); super(originalKey); } } Loading Loading @@ -151,7 +156,7 @@ public class DynamicGridKeyboard extends Keyboard { @Override @Override public String toString() { public String toString() { return "RecentKey: " + super.toString(); return "GridKey: " + super.toString(); } } } } } } Loading
java/src/com/android/inputmethod/keyboard/EmojiKeyboardView.java +92 −19 Original line number Original line Diff line number Diff line Loading @@ -22,6 +22,7 @@ import android.content.Context; import android.content.res.ColorStateList; import android.content.res.ColorStateList; import android.content.res.Resources; import android.content.res.Resources; import android.content.res.TypedArray; import android.content.res.TypedArray; import android.graphics.Rect; import android.os.Build; import android.os.Build; import android.support.v4.view.PagerAdapter; import android.support.v4.view.PagerAdapter; import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager; Loading @@ -37,7 +38,9 @@ import android.widget.TabHost; import android.widget.TabHost.OnTabChangeListener; import android.widget.TabHost.OnTabChangeListener; import android.widget.TextView; import android.widget.TextView; import com.android.inputmethod.keyboard.internal.CodesArrayParser; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; import com.android.inputmethod.keyboard.internal.DynamicGridKeyboard; import com.android.inputmethod.keyboard.internal.KeyboardParams; import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; import com.android.inputmethod.keyboard.internal.ScrollKeyboardView; import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier; import com.android.inputmethod.latin.Constants; import com.android.inputmethod.latin.Constants; Loading @@ -47,7 +50,10 @@ import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import com.android.inputmethod.latin.utils.ResourceUtils; import java.util.ArrayList; import java.util.ArrayList; import java.util.Arrays; import java.util.Comparator; import java.util.HashMap; import java.util.HashMap; import java.util.concurrent.ConcurrentHashMap; /** /** * View class to implement Emoji keyboards. * View class to implement Emoji keyboards. Loading Loading @@ -75,8 +81,6 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER; private static class EmojiCategory { private int mCurrentCategory = CATEGORY_UNSPECIFIED; private static final int CATEGORY_UNSPECIFIED = -1; private static final int CATEGORY_UNSPECIFIED = -1; private static final int CATEGORY_RECENTS = 0; private static final int CATEGORY_RECENTS = 0; private static final int CATEGORY_PEOPLE = 1; private static final int CATEGORY_PEOPLE = 1; Loading @@ -85,6 +89,9 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange private static final int CATEGORY_PLACES = 4; private static final int CATEGORY_PLACES = 4; private static final int CATEGORY_SYMBOLS = 5; private static final int CATEGORY_SYMBOLS = 5; private static final int CATEGORY_EMOTICONS = 6; private static final int CATEGORY_EMOTICONS = 6; private static class EmojiCategory { private static final int DEFAULT_MAX_ROW_SIZE = 3; private static final String[] sCategoryName = { private static final String[] sCategoryName = { "recents", "recents", "people", "people", Loading @@ -111,10 +118,18 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange KeyboardId.ELEMENT_EMOJI_CATEGORY4, KeyboardId.ELEMENT_EMOJI_CATEGORY4, KeyboardId.ELEMENT_EMOJI_CATEGORY5, KeyboardId.ELEMENT_EMOJI_CATEGORY5, KeyboardId.ELEMENT_EMOJI_CATEGORY6, }; KeyboardId.ELEMENT_EMOJI_CATEGORY6, }; private Resources mRes; private final KeyboardLayoutSet mLayoutSet; private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap(); private final HashMap<String, Integer> mCategoryNameToIdMap = CollectionUtils.newHashMap(); private final ArrayList<Integer> mShownCategories = new ArrayList<Integer>(); private final ArrayList<Integer> mShownCategories = new ArrayList<Integer>(); private final ConcurrentHashMap<Long, DynamicGridKeyboard> mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>(); public EmojiCategory() { private int mCurrentCategory = CATEGORY_UNSPECIFIED; public EmojiCategory(final Resources res, final KeyboardLayoutSet layoutSet) { mRes = res; mLayoutSet = layoutSet; for (int i = 0; i < sCategoryName.length; ++i) { for (int i = 0; i < sCategoryName.length; ++i) { mCategoryNameToIdMap.put(sCategoryName[i], i); mCategoryNameToIdMap.put(sCategoryName[i], i); } } Loading Loading @@ -185,12 +200,71 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange return mShownCategories.get(tabId); return mShownCategories.get(tabId); } } public int getElementIdFromTabId(int tabId) { public DynamicGridKeyboard getKeyboard(int category, int id) { return sCategoryElementId[getCategoryFromTabId(tabId)]; synchronized(mCategoryKeyboardMap) { final long key = (((long) category) << 32) | id; final DynamicGridKeyboard kbd; if (!mCategoryKeyboardMap.containsKey(key)) { if (category != CATEGORY_RECENTS) { kbd = new DynamicGridKeyboard( mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), DEFAULT_MAX_ROW_SIZE); final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[category]); // TODO: Calculate maxPageCount dynamically final Key[][] sortedKeys = sortKeys(keyboard.getKeys(), 21); for (Key emojiKey : sortedKeys[0]) { if (emojiKey == null) { break; } kbd.addKeyLast(emojiKey); } } else { kbd = new DynamicGridKeyboard( mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), DEFAULT_MAX_ROW_SIZE); } mCategoryKeyboardMap.put(key, kbd); } else { kbd = mCategoryKeyboardMap.get(key); } return kbd; } } private Key[][] sortKeys(Key[] inKeys, int maxPageCount) { Key[] keys = Arrays.copyOf(inKeys, inKeys.length); Arrays.sort(keys, 0, keys.length, new Comparator<Key>() { @Override public int compare(Key lhs, 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; } }); final int pageCount = (keys.length - 1) / maxPageCount + 1; final Key[][] retval = new Key[pageCount][maxPageCount]; for (int i = 0; i < keys.length; ++i) { retval[i / maxPageCount][i % maxPageCount] = keys[i]; } return retval; } } } } private final EmojiCategory mEmojiCategory = new EmojiCategory(); private final EmojiCategory mEmojiCategory; public EmojiKeyboardView(final Context context, final AttributeSet attrs) { public EmojiKeyboardView(final Context context, final AttributeSet attrs) { this(context, attrs, R.attr.emojiKeyboardViewStyle); this(context, attrs, R.attr.emojiKeyboardViewStyle); Loading Loading @@ -219,6 +293,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange + res.getDimensionPixelSize(R.dimen.suggestions_strip_height)); + res.getDimensionPixelSize(R.dimen.suggestions_strip_height)); builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */); builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */); mLayoutSet = builder.build(); mLayoutSet = builder.build(); mEmojiCategory = new EmojiCategory(context.getResources(), builder.build()); // TODO: Save/restore recent keys from/to preferences. // TODO: Save/restore recent keys from/to preferences. } } Loading Loading @@ -388,15 +463,14 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange mEmojiCategory = emojiCategory; mEmojiCategory = emojiCategory; mListener = listener; mListener = listener; mLayoutSet = layoutSet; mLayoutSet = layoutSet; mRecentsKeyboard = new DynamicGridKeyboard( mRecentsKeyboard = mEmojiCategory.getKeyboard(CATEGORY_RECENTS, 0); layoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS)); } } public void addRecentKey(final Key key) { public void addRecentKey(final Key key) { if (mEmojiCategory.isInRecentTab()) { if (mEmojiCategory.isInRecentTab()) { return; return; } } mRecentsKeyboard.addRecentKey(key); mRecentsKeyboard.addKeyFirst(key); final KeyboardView recentKeyboardView = final KeyboardView recentKeyboardView = mActiveKeyboardView.get(mEmojiCategory.getRecentTabId()); mActiveKeyboardView.get(mEmojiCategory.getRecentTabId()); if (recentKeyboardView != null) { if (recentKeyboardView != null) { Loading Loading @@ -424,9 +498,8 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange @Override @Override public Object instantiateItem(final ViewGroup container, final int position) { public Object instantiateItem(final ViewGroup container, final int position) { final int elementId = mEmojiCategory.getElementIdFromTabId(position); final Keyboard keyboard = final Keyboard keyboard = (elementId == KeyboardId.ELEMENT_EMOJI_RECENTS) mEmojiCategory.getKeyboard(mEmojiCategory.getCategoryFromTabId(position), 0); ? mRecentsKeyboard : mLayoutSet.getKeyboard(elementId); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); final LayoutInflater inflater = LayoutInflater.from(container.getContext()); final View view = inflater.inflate( final View view = inflater.inflate( R.layout.emoji_keyboard_page, container, false /* attachToRoot */); R.layout.emoji_keyboard_page, container, false /* attachToRoot */); Loading
java/src/com/android/inputmethod/keyboard/internal/DynamicGridKeyboard.java +35 −30 Original line number Original line Diff line number Diff line Loading @@ -23,7 +23,6 @@ import com.android.inputmethod.keyboard.Keyboard; import com.android.inputmethod.latin.utils.CollectionUtils; import com.android.inputmethod.latin.utils.CollectionUtils; import java.util.ArrayDeque; import java.util.ArrayDeque; import java.util.Random; /** /** * This is a Keyboard class where you can add keys dynamically shown in a grid layout * This is a Keyboard class where you can add keys dynamically shown in a grid layout Loading @@ -37,12 +36,12 @@ public class DynamicGridKeyboard extends Keyboard { private final int mHorizontalStep; private final int mHorizontalStep; private final int mVerticalStep; private final int mVerticalStep; private final int mColumnsNum; private final int mColumnsNum; private final int mMaxRecentKeyCount; private final int mMaxKeyCount; private final ArrayDeque<RecentKey> mRecentKeys = CollectionUtils.newArrayDeque(); private final ArrayDeque<GridKey> mGridKeys = CollectionUtils.newArrayDeque(); private Key[] mCachedRecentKeys; private Key[] mCachedGridKeys; public DynamicGridKeyboard(final Keyboard templateKeyboard) { public DynamicGridKeyboard(final Keyboard templateKeyboard, final int maxRows) { super(templateKeyboard); super(templateKeyboard); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key0 = getTemplateKey(TEMPLATE_KEY_CODE_0); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); final Key key1 = getTemplateKey(TEMPLATE_KEY_CODE_1); Loading @@ -50,8 +49,7 @@ public class DynamicGridKeyboard extends Keyboard { mHorizontalStep = Math.abs(key1.getX() - key0.getX()); mHorizontalStep = Math.abs(key1.getX() - key0.getX()); mVerticalStep = key0.getHeight() + mVerticalGap; mVerticalStep = key0.getHeight() + mVerticalGap; mColumnsNum = mBaseWidth / mHorizontalStep; mColumnsNum = mBaseWidth / mHorizontalStep; final int rowsNum = mBaseHeight / mVerticalStep; mMaxKeyCount = mColumnsNum * maxRows; mMaxRecentKeyCount = mColumnsNum * rowsNum; } } private Key getTemplateKey(final int code) { private Key getTemplateKey(final int code) { Loading @@ -63,27 +61,34 @@ public class DynamicGridKeyboard extends Keyboard { throw new RuntimeException("Can't find template key: code=" + code); throw new RuntimeException("Can't find template key: code=" + code); } } private final Random random = new Random(); public void addKeyFirst(final Key usedKey) { addKey(usedKey, true); } public void addKeyLast(final Key usedKey) { addKey(usedKey, false); } public void addRecentKey(final Key usedKey) { private void addKey(final Key usedKey, final boolean addFirst) { synchronized (mRecentKeys) { synchronized (mGridKeys) { mCachedRecentKeys = null; mCachedGridKeys = null; final RecentKey key = (usedKey instanceof RecentKey) final GridKey key = new GridKey(usedKey); ? (RecentKey)usedKey : new RecentKey(usedKey); while (mGridKeys.remove(key)) { while (mRecentKeys.remove(key)) { // Remove duplicate keys. // Remove duplicate keys. } } mRecentKeys.addFirst(key); if (addFirst) { while (mRecentKeys.size() > mMaxRecentKeyCount) { mGridKeys.addFirst(key); mRecentKeys.removeLast(); } else { mGridKeys.addLast(key); } while (mGridKeys.size() > mMaxKeyCount) { mGridKeys.removeLast(); } } int index = 0; int index = 0; for (final RecentKey recentKey : mRecentKeys) { for (final GridKey gridKey : mGridKeys) { final int keyX = getKeyX(index); final int keyX = getKeyX(index); final int keyY = getKeyY(index); final int keyY = getKeyY(index); final int x = keyX+random.nextInt(recentKey.getWidth()); gridKey.updateCorrdinates(keyX, keyY); final int y = keyY+random.nextInt(recentKey.getHeight()); recentKey.updateCorrdinates(keyX, keyY); index++; index++; } } } } Loading @@ -101,26 +106,26 @@ public class DynamicGridKeyboard extends Keyboard { @Override @Override public Key[] getKeys() { public Key[] getKeys() { synchronized (mRecentKeys) { synchronized (mGridKeys) { if (mCachedRecentKeys != null) { if (mCachedGridKeys != null) { return mCachedRecentKeys; return mCachedGridKeys; } } mCachedRecentKeys = mRecentKeys.toArray(new Key[mRecentKeys.size()]); mCachedGridKeys = mGridKeys.toArray(new Key[mGridKeys.size()]); return mCachedRecentKeys; return mCachedGridKeys; } } } } @Override @Override public Key[] getNearestKeys(final int x, final int y) { public Key[] getNearestKeys(final int x, final int y) { // TODO: Calculate the nearest key index in mRecentKeys from x and y. // TODO: Calculate the nearest key index in mGridKeys from x and y. return getKeys(); return getKeys(); } } static final class RecentKey extends Key { static final class GridKey extends Key { private int mCurrentX; private int mCurrentX; private int mCurrentY; private int mCurrentY; public RecentKey(final Key originalKey) { public GridKey(final Key originalKey) { super(originalKey); super(originalKey); } } Loading Loading @@ -151,7 +156,7 @@ public class DynamicGridKeyboard extends Keyboard { @Override @Override public String toString() { public String toString() { return "RecentKey: " + super.toString(); return "GridKey: " + super.toString(); } } } } } }