Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3c9c1103 authored by Satoshi Kataoka's avatar Satoshi Kataoka Committed by Android Git Automerger
Browse files

am cdc2ce8c: Merge "Use DynamicGridKeyboard for EmojiPager"

* commit 'cdc2ce8c':
  Use DynamicGridKeyboard for EmojiPager
parents db5ec997 cdc2ce8c
Loading
Loading
Loading
Loading
+92 −19
Original line number Original line Diff line number Diff line
@@ -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;
@@ -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;
@@ -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.
@@ -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;
@@ -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",
@@ -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);
            }
            }
@@ -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);
@@ -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.
    }
    }


@@ -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) {
@@ -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 */);
+35 −30
Original line number Original line Diff line number Diff line
@@ -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
@@ -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);
@@ -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) {
@@ -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++;
            }
            }
        }
        }
@@ -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);
        }
        }


@@ -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();
        }
        }
    }
    }
}
}