Split Emoji categories fitting the pager

Bug: 10538430
Change-Id: Ic023ac0b9db8a1fe16c73ab5fd12dfcd7cbbe6a3
main
Satoshi Kataoka 2013-09-13 21:49:53 +09:00
parent 0f317a5603
commit 5dfbc8af24
6 changed files with 135 additions and 45 deletions

View File

@ -75,5 +75,9 @@
<dimen name="gesture_floating_preview_vertical_padding">15dp</dimen> <dimen name="gesture_floating_preview_vertical_padding">15dp</dimen>
<!-- Emoji keyboard --> <!-- Emoji keyboard -->
<fraction name="emoji_keyboard_key_width">8.3333%p</fraction> <fraction name="emoji_keyboard_key_width">10%p</fraction>
<fraction name="emoji_keyboard_row_height">50%p</fraction>
<fraction name="emoji_keyboard_key_letter_size">60%p</fraction>
<integer name="emoji_keyboard_max_key_count">20</integer>
</resources> </resources>

View File

@ -117,6 +117,9 @@
<!-- Emoji keyboard --> <!-- Emoji keyboard -->
<fraction name="emoji_keyboard_key_width">14.2857%p</fraction> <fraction name="emoji_keyboard_key_width">14.2857%p</fraction>
<fraction name="emoji_keyboard_row_height">33%p</fraction>
<fraction name="emoji_keyboard_key_letter_size">90%p</fraction>
<integer name="emoji_keyboard_max_key_count">21</integer>
<!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. --> <!-- Inset used in Accessibility mode to avoid accidental key presses when a finger slides off the screen. -->
<dimen name="accessibility_edge_slop">8dp</dimen> <dimen name="accessibility_edge_slop">8dp</dimen>
@ -124,4 +127,5 @@
<integer name="user_dictionary_max_word_length" translatable="false">48</integer> <integer name="user_dictionary_max_word_length" translatable="false">48</integer>
<dimen name="language_on_spacebar_horizontal_margin">1dp</dimen> <dimen name="language_on_spacebar_horizontal_margin">1dp</dimen>
</resources> </resources>

View File

@ -21,8 +21,9 @@
<Keyboard <Keyboard
xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin" xmlns:latin="http://schemas.android.com/apk/res/com.android.inputmethod.latin"
latin:keyWidth="@fraction/emoji_keyboard_key_width" latin:keyWidth="@fraction/emoji_keyboard_key_width"
latin:keyLetterSize="90%p" latin:keyLetterSize="@fraction/emoji_keyboard_key_letter_size"
latin:keyLabelSize="60%p" latin:keyLabelSize="60%p"
latin:rowHeight="@fraction/emoji_keyboard_row_height"
> >
<GridRows <GridRows
latin:codesArray="@array/emoji_recents" latin:codesArray="@array/emoji_recents"

View File

@ -28,6 +28,7 @@ import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager; import android.support.v4.view.ViewPager;
import android.util.AttributeSet; import android.util.AttributeSet;
import android.util.Log; import android.util.Log;
import android.util.Pair;
import android.util.SparseArray; import android.util.SparseArray;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
@ -38,9 +39,7 @@ 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;
@ -90,7 +89,17 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
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 CategoryProperties {
public int mCategory;
public int mPageCount;
public CategoryProperties(final int category, final int pageCount) {
mCategory = category;
mPageCount = pageCount;
}
}
private static class EmojiCategory { private static class EmojiCategory {
private static final int DEFAULT_PAGE_KEY_COUNT = 21;
private static final int DEFAULT_MAX_ROW_SIZE = 3; private static final int DEFAULT_MAX_ROW_SIZE = 3;
private static final String[] sCategoryName = { private static final String[] sCategoryName = {
"recents", "recents",
@ -118,10 +127,12 @@ 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 Resources mRes;
private final int mMaxPageKeyCount;
private final KeyboardLayoutSet mLayoutSet; 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<CategoryProperties> mShownCategories =
CollectionUtils.newArrayList();
private final ConcurrentHashMap<Long, DynamicGridKeyboard> private final ConcurrentHashMap<Long, DynamicGridKeyboard>
mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>(); mCategoryKeyboardMap = new ConcurrentHashMap<Long, DynamicGridKeyboard>();
@ -129,32 +140,42 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
public EmojiCategory(final Resources res, final KeyboardLayoutSet layoutSet) { public EmojiCategory(final Resources res, final KeyboardLayoutSet layoutSet) {
mRes = res; mRes = res;
mMaxPageKeyCount = res.getInteger(R.integer.emoji_keyboard_max_key_count);
mLayoutSet = layoutSet; 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);
} }
mShownCategories.add(CATEGORY_RECENTS); addShownCategory(CATEGORY_RECENTS);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
mShownCategories.add(CATEGORY_PEOPLE); addShownCategory(CATEGORY_PEOPLE);
mShownCategories.add(CATEGORY_OBJECTS); addShownCategory(CATEGORY_OBJECTS);
mShownCategories.add(CATEGORY_NATURE); addShownCategory(CATEGORY_NATURE);
mShownCategories.add(CATEGORY_PLACES); addShownCategory(CATEGORY_PLACES);
// TODO: Restore last saved category // TODO: Restore last saved category
mCurrentCategory = CATEGORY_PEOPLE; mCurrentCategory = CATEGORY_PEOPLE;
} else { } else {
// TODO: Restore last saved category // TODO: Restore last saved category
mCurrentCategory = CATEGORY_SYMBOLS; mCurrentCategory = CATEGORY_SYMBOLS;
} }
mShownCategories.add(CATEGORY_SYMBOLS); addShownCategory(CATEGORY_SYMBOLS);
mShownCategories.add(CATEGORY_EMOTICONS); addShownCategory(CATEGORY_EMOTICONS);
} }
public String getCategoryName(int category) { private void addShownCategory(int category) {
return sCategoryName[category]; // Load a keyboard of category
getKeyboard(category, 0);
final CategoryProperties properties =
new CategoryProperties(category, getCategoryPageCount(category));
mShownCategories.add(properties);
}
public String getCategoryName(int category, int categoryPageId) {
return sCategoryName[category] + "-" + categoryPageId;
} }
public int getCategoryId(String name) { public int getCategoryId(String name) {
return mCategoryNameToIdMap.get(name); final String[] strings = name.split("-");
return mCategoryNameToIdMap.get(strings[0]);
} }
public int getCategoryIcon(int category) { public int getCategoryIcon(int category) {
@ -165,7 +186,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
return sCategoryLabel[category]; return sCategoryLabel[category];
} }
public ArrayList<Integer> getShownCategories() { public ArrayList<CategoryProperties> getShownCategories() {
return mShownCategories; return mShownCategories;
} }
@ -184,7 +205,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
public int getTabIdFromCategory(int category) { public int getTabIdFromCategory(int category) {
for (int i = 0; i < mShownCategories.size(); ++i) { for (int i = 0; i < mShownCategories.size(); ++i) {
if (mShownCategories.get(i) == category) { if (mShownCategories.get(i).mCategory == category) {
return i; return i;
} }
} }
@ -192,12 +213,53 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
return 0; return 0;
} }
// Returns the view pager's page position for the category
public int getPageIdFromCategory(int category) {
int sum = 0;
for (int i = 0; i < mShownCategories.size(); ++i) {
final CategoryProperties props = mShownCategories.get(i);
if (props.mCategory == category) {
return sum;
}
sum += props.mPageCount;
}
Log.w(TAG, "category not found: " + category);
return 0;
}
public int getRecentTabId() { public int getRecentTabId() {
return getTabIdFromCategory(CATEGORY_RECENTS); return getTabIdFromCategory(CATEGORY_RECENTS);
} }
public int getCategoryFromTabId(int tabId) { private int getCategoryPageCount(int category) {
return mShownCategories.get(tabId); final Keyboard keyboard = mLayoutSet.getKeyboard(sCategoryElementId[category]);
return (keyboard.getKeys().length - 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(int position) {
int sum = 0;
for (CategoryProperties properties : mShownCategories) {
final int temp = sum;
sum += properties.mPageCount;
if (sum > position) {
return new Pair<Integer, Integer>(properties.mCategory, position - temp);
}
}
return null;
}
// Returns a keyboard from the view pager's page position.
public DynamicGridKeyboard getKeyboardFromPagePosition(int position) {
final Pair<Integer, Integer> categoryAndId =
getCategoryIdAndPageIdFromPagePosition(position);
if (categoryAndId != null) {
return getKeyboard(categoryAndId.first, categoryAndId.second);
}
return null;
} }
public DynamicGridKeyboard getKeyboard(int category, int id) { public DynamicGridKeyboard getKeyboard(int category, int id) {
@ -206,25 +268,29 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
final DynamicGridKeyboard kbd; final DynamicGridKeyboard kbd;
if (!mCategoryKeyboardMap.containsKey(key)) { if (!mCategoryKeyboardMap.containsKey(key)) {
if (category != CATEGORY_RECENTS) { if (category != CATEGORY_RECENTS) {
kbd = new DynamicGridKeyboard(
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
DEFAULT_MAX_ROW_SIZE);
final Keyboard keyboard = final Keyboard keyboard =
mLayoutSet.getKeyboard(sCategoryElementId[category]); mLayoutSet.getKeyboard(sCategoryElementId[category]);
// TODO: Calculate maxPageCount dynamically // TODO: Calculate maxPageCount dynamically
final Key[][] sortedKeys = sortKeys(keyboard.getKeys(), 21); final Key[][] sortedKeys = sortKeys(keyboard.getKeys(), mMaxPageKeyCount);
for (Key emojiKey : sortedKeys[0]) { for (int i = 0; i < sortedKeys.length; ++i) {
if (emojiKey == null) { final DynamicGridKeyboard tempKbd = new DynamicGridKeyboard(
break; mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
mMaxPageKeyCount);
for (Key emojiKey : sortedKeys[i]) {
if (emojiKey == null) {
break;
}
tempKbd.addKeyLast(emojiKey);
} }
kbd.addKeyLast(emojiKey); mCategoryKeyboardMap.put((((long) category) << 32) | i, tempKbd);
} }
kbd = mCategoryKeyboardMap.get(key);
} else { } else {
kbd = new DynamicGridKeyboard( kbd = new DynamicGridKeyboard(
mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS), mLayoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS),
DEFAULT_MAX_ROW_SIZE); mMaxPageKeyCount);
mCategoryKeyboardMap.put(key, kbd);
} }
mCategoryKeyboardMap.put(key, kbd);
} else { } else {
kbd = mCategoryKeyboardMap.get(key); kbd = mCategoryKeyboardMap.get(key);
} }
@ -232,6 +298,14 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
} }
} }
public int getTotalPageCountOfAllCategories() {
int sum = 0;
for (CategoryProperties properties : mShownCategories) {
sum += properties.mPageCount;
}
return sum;
}
private Key[][] sortKeys(Key[] inKeys, int maxPageCount) { private Key[][] sortKeys(Key[] inKeys, int maxPageCount) {
Key[] keys = Arrays.copyOf(inKeys, inKeys.length); Key[] keys = Arrays.copyOf(inKeys, inKeys.length);
Arrays.sort(keys, 0, keys.length, new Comparator<Key>() { Arrays.sort(keys, 0, keys.length, new Comparator<Key>() {
@ -287,10 +361,10 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder( final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
context, null /* editorInfo */); context, null /* editorInfo */);
final Resources res = context.getResources(); final Resources res = context.getResources();
final EmojiLayoutParams emojiLp = new EmojiLayoutParams(res);
builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype()); builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype());
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res), builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
(int)ResourceUtils.getDefaultKeyboardHeight(res) emojiLp.mEmojiKeyboardHeight);
+ 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()); mEmojiCategory = new EmojiCategory(context.getResources(), builder.build());
@ -311,7 +385,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
} }
private void addTab(final TabHost host, final int category) { private void addTab(final TabHost host, final int category) {
final String tabId = mEmojiCategory.getCategoryName(category); final String tabId = mEmojiCategory.getCategoryName(category, 0 /* categoryPageId */);
final TabHost.TabSpec tspec = host.newTabSpec(tabId); final TabHost.TabSpec tspec = host.newTabSpec(tabId);
tspec.setContent(R.id.emoji_keyboard_dummy); tspec.setContent(R.id.emoji_keyboard_dummy);
if (mEmojiCategory.getCategoryIcon(category) != 0) { if (mEmojiCategory.getCategoryIcon(category) != 0) {
@ -334,8 +408,8 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
protected void onFinishInflate() { protected void onFinishInflate() {
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost); mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
mTabHost.setup(); mTabHost.setup();
for (final int i : mEmojiCategory.getShownCategories()) { for (final CategoryProperties properties : mEmojiCategory.getShownCategories()) {
addTab(mTabHost, i); addTab(mTabHost, properties.mCategory);
} }
mTabHost.setOnTabChangedListener(this); mTabHost.setOnTabChangedListener(this);
mTabHost.getTabWidget().setStripEnabled(true); mTabHost.getTabWidget().setStripEnabled(true);
@ -384,7 +458,8 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override @Override
public void onPageSelected(final int position) { public void onPageSelected(final int position) {
setCurrentCategory(mEmojiCategory.getCategoryFromTabId(position), false /* force */); setCurrentCategory(mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(position).first,
false /* force */);
} }
@Override @Override
@ -439,8 +514,10 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
mEmojiCategory.setCurrentCategory(category); mEmojiCategory.setCurrentCategory(category);
final int newTabId = mEmojiCategory.getTabIdFromCategory(category); final int newTabId = mEmojiCategory.getTabIdFromCategory(category);
if (force || mEmojiPager.getCurrentItem() != newTabId) { final int newCategoryPageId = mEmojiCategory.getPageIdFromCategory(category);
mEmojiPager.setCurrentItem(newTabId, true /* smoothScroll */); if (force || mEmojiCategory.getCategoryIdAndPageIdFromPagePosition(
mEmojiPager.getCurrentItem()).first != category) {
mEmojiPager.setCurrentItem(newCategoryPageId, true /* smoothScroll */);
} }
if (force || mTabHost.getCurrentTab() != newTabId) { if (force || mTabHost.getCurrentTab() != newTabId) {
mTabHost.setCurrentTab(newTabId); mTabHost.setCurrentTab(newTabId);
@ -480,7 +557,7 @@ public final class EmojiKeyboardView extends LinearLayout implements OnTabChange
@Override @Override
public int getCount() { public int getCount() {
return mEmojiCategory.getShownCategories().size(); return mEmojiCategory.getTotalPageCountOfAllCategories();
} }
@Override @Override
@ -499,7 +576,7 @@ 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 Keyboard keyboard = final Keyboard keyboard =
mEmojiCategory.getKeyboard(mEmojiCategory.getCategoryFromTabId(position), 0); mEmojiCategory.getKeyboardFromPagePosition(position);
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 */);

View File

@ -27,6 +27,8 @@ import android.widget.LinearLayout;
public class EmojiLayoutParams { public class EmojiLayoutParams {
private static final int DEFAULT_KEYBOARD_ROWS = 4; private static final int DEFAULT_KEYBOARD_ROWS = 4;
public final int mEmojiPagerHeight;
private final int mEmojiPagerBottomMargin;
public final int mEmojiKeyboardHeight; public final int mEmojiKeyboardHeight;
public final int mEmojiActionBarHeight; public final int mEmojiActionBarHeight;
public final int mKeyVerticalGap; public final int mKeyVerticalGap;
@ -49,13 +51,15 @@ public class EmojiLayoutParams {
+ mKeyVerticalGap; + mKeyVerticalGap;
mEmojiActionBarHeight = ((int) baseheight) / DEFAULT_KEYBOARD_ROWS mEmojiActionBarHeight = ((int) baseheight) / DEFAULT_KEYBOARD_ROWS
- (mKeyVerticalGap - mBottomPadding) / 2; - (mKeyVerticalGap - mBottomPadding) / 2;
mEmojiKeyboardHeight = defaultKeyboardHeight - mEmojiActionBarHeight; mEmojiPagerHeight = defaultKeyboardHeight - mEmojiActionBarHeight;
mEmojiPagerBottomMargin = mKeyVerticalGap / 2;
mEmojiKeyboardHeight = mEmojiPagerHeight - mEmojiPagerBottomMargin - 1;
} }
public void setPagerProps(ViewPager vp) { public void setPagerProps(ViewPager vp) {
final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) vp.getLayoutParams(); final LinearLayout.LayoutParams lp = (LinearLayout.LayoutParams) vp.getLayoutParams();
lp.height = mEmojiKeyboardHeight - mKeyVerticalGap / 2; lp.height = mEmojiPagerHeight - mEmojiPagerBottomMargin;
lp.bottomMargin = mKeyVerticalGap / 2; lp.bottomMargin = mEmojiPagerBottomMargin;
vp.setLayoutParams(lp); vp.setLayoutParams(lp);
} }

View File

@ -41,7 +41,7 @@ public class DynamicGridKeyboard extends Keyboard {
private Key[] mCachedGridKeys; private Key[] mCachedGridKeys;
public DynamicGridKeyboard(final Keyboard templateKeyboard, final int maxRows) { public DynamicGridKeyboard(final Keyboard templateKeyboard, final int maxKeyCount) {
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);
@ -49,7 +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;
mMaxKeyCount = mColumnsNum * maxRows; mMaxKeyCount = maxKeyCount;
} }
private Key getTemplateKey(final int code) { private Key getTemplateKey(final int code) {