Support Emoji keyboard

Bug: 6370846
Change-Id: I33ce8f952799c89929996a226ac17731a953ec2a
main
Tadashi G. Takaoka 2013-08-28 09:17:38 +09:00
parent b384cb28a1
commit d7791a93b0
14 changed files with 143 additions and 49 deletions

View File

@ -20,26 +20,33 @@
<com.android.inputmethod.latin.InputView <com.android.inputmethod.latin.InputView
xmlns:android="http://schemas.android.com/apk/res/android" xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:gravity="bottom|center_horizontal" android:gravity="bottom|center_horizontal"
> android:orientation="vertical" >
<!-- To ensure that key preview popup is correctly placed when the current system locale is <include
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. --> layout="@layout/emoji_keyboard_view" />
<com.android.inputmethod.latin.suggestions.SuggestionStripView <LinearLayout
android:id="@+id/suggestion_strip_view" android:id="@+id/main_keyboard_frame"
android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="@dimen/suggestions_strip_height"
android:paddingRight="@dimen/suggestions_strip_padding"
android:paddingLeft="@dimen/suggestions_strip_padding"
style="?attr/suggestionStripViewStyle" />
<!-- To ensure that key preview popup is correctly placed when the current system locale is
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<com.android.inputmethod.keyboard.MainKeyboardView
android:id="@+id/keyboard_view"
android:layoutDirection="ltr"
android:layout_width="wrap_content" android:layout_width="wrap_content"
android:layout_height="wrap_content" /> android:layout_height="wrap_content"
android:orientation="vertical" >
<!-- To ensure that key preview popup is correctly placed when the current system locale is
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<com.android.inputmethod.latin.suggestions.SuggestionStripView
android:id="@+id/suggestion_strip_view"
android:layoutDirection="ltr"
android:layout_width="match_parent"
android:layout_height="@dimen/suggestions_strip_height"
android:paddingRight="@dimen/suggestions_strip_padding"
android:paddingLeft="@dimen/suggestions_strip_padding"
style="?attr/suggestionStripViewStyle" />
<!-- To ensure that key preview popup is correctly placed when the current system locale is
one of RTL locales, layoutDirection="ltr" is needed in the SDK version 17+. -->
<com.android.inputmethod.keyboard.MainKeyboardView
android:id="@+id/keyboard_view"
android:layoutDirection="ltr"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</LinearLayout>
</com.android.inputmethod.latin.InputView> </com.android.inputmethod.latin.InputView>

View File

@ -36,26 +36,73 @@
name="emoji_nature" name="emoji_nature"
format="string" format="string"
> >
<item>2744</item> <!-- SNOWFLAKE -->
</array> </array>
<array <array
name="emoji_symbols" name="emoji_symbols"
format="string" format="string"
> >
<item>2460</item> <!-- CIRCLED DIGIT ONE -->
<item>2461</item> <!-- CIRCLED DIGIT TWO -->
<item>2462</item> <!-- CIRCLED DIGIT THREE -->
<item>2463</item> <!-- CIRCLED DIGIT FOUR -->
<item>2464</item> <!-- CIRCLED DIGIT FIVE -->
<item>2465</item> <!-- CIRCLED DIGIT SIX -->
<item>2466</item> <!-- CIRCLED DIGIT SEVEN -->
<item>2467</item> <!-- CIRCLED DIGIT EIGHT -->
<item>2468</item> <!-- CIRCLED DIGIT NINE -->
<item>2469</item> <!-- CIRCLED DIGIT TEN -->
<item>00ae</item> <!-- REGISTERED SIGN -->
<item>00a9</item> <!-- COPYRIGHT SIGN -->
<item>2122</item> <!-- TRADE MARK SIGN -->
<item>2734</item> <!-- EIGHT POINTED BLACK STAR -->
<item>2733</item> <!-- EIGHT POINTED PINWHEEL STAR -->
<item>2716</item> <!-- HEAVY MULTIPLICATION MARK -->
<item>2195</item> <!-- UP DOWN ARROW -->
<item>2197</item> <!-- NORTH EAST ARROW -->
<item>27a1</item> <!-- BLACK RIGHTWARDS ARROW -->
<item>2198</item> <!-- SOUTH EAST ARROW -->
<item>2199</item> <!-- SOUTH WEST ARROW -->
<item>2196</item> <!-- NORTH EAST ARROW -->
<item>2194</item> <!-- LEFT RIGHT ARROW -->
<item>25c0</item> <!-- BLACK LEFT-POINTING TRIANGLE -->
<item>25b6</item> <!-- BLACK ROGHT-POINTING TRIANGLE -->
<item>2747</item> <!-- SPARKLE -->
<item>25aa</item> <!-- BLACK SMALL SQUARE -->
<item>203c</item> <!-- DOUBLE EXCLAMATION MARK -->
<item>2660</item> <!-- BLACK SPADE SUIT -->
<item>2665</item> <!-- BLACK HEART SUIT -->
<item>2663</item> <!-- BLACK CLUB SUIT -->
<item>2666</item> <!-- BLACK DIAMOND SUIT -->
<item>21a9</item> <!-- LEFTWARDS ARROW WITH HOOK -->
<item>21aa</item> <!-- RIGHTWARDS ARROW WITH HOOK -->
</array> </array>
<array <array
name="emoji_faces" name="emoji_faces"
format="string" format="string"
> >
<item>270C</item> <!-- VICTORY HAND -->
<item>2764</item> <!-- HEAVY BLACK HEART -->
</array> </array>
<array <array
name="emoji_objects" name="emoji_objects"
format="string" format="string"
> >
<item>260e</item> <!-- BLACK TELEPHONE -->
<item>2709</item> <!-- ENVELOPE -->
<item>2712</item> <!-- BLACK NIB -->
<item>270f</item> <!-- PENCIL -->
<item>2702</item> <!-- BLACK SCISSORS -->
<item>2669</item> <!-- QUARTER NOTE -->
<item>266a</item> <!-- EIGHTH NOTE -->
<item>266c</item> <!-- BEAMED SIXTEENTH NOTES -->
</array> </array>
<array <array
name="emoji_places" name="emoji_places"
format="string" format="string"
> >
<item>2708</item> <!-- AIRPLANE -->
<item>2668</item> <!-- HOT SPRINGS -->
</array> </array>
<array <array
name="emoji_emoticons" name="emoji_emoticons"

View File

@ -104,7 +104,14 @@
<style <style
name="MainKeyboardView" name="MainKeyboardView"
parent="KeyboardView" /> parent="KeyboardView" />
<style name="EmojiKeyboardView" /> <!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style
name="EmojiKeyboardView"
parent="KeyboardView"
>
<item name="emojiTabLabelColor">@color/emoji_tab_label_color_ics</item>
</style>
<style name="MoreKeysKeyboard" /> <style name="MoreKeysKeyboard" />
<style <style
name="MoreKeysKeyboardView" name="MoreKeysKeyboardView"

View File

@ -96,6 +96,8 @@
<item name="spacebarTextColor">@color/spacebar_text_color_gb</item> <item name="spacebarTextColor">@color/spacebar_text_color_gb</item>
<item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_gb</item> <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_gb</item>
</style> </style>
<!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style <style
name="EmojiKeyboardView.GB" name="EmojiKeyboardView.GB"
parent="KeyboardView.GB" parent="KeyboardView.GB"

View File

@ -97,6 +97,8 @@
<item name="spacebarTextColor">@color/spacebar_text_color_ics</item> <item name="spacebarTextColor">@color/spacebar_text_color_ics</item>
<item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_ics</item> <item name="spacebarTextShadowColor">@color/spacebar_text_shadow_color_ics</item>
</style> </style>
<!-- Though {@link EmojiKeyboardView} doesn't extend {@link KeyboardView}, some views inside it,
for instance delete button, need themed {@link KeyboardView} attributes. -->
<style <style
name="EmojiKeyboardView.ICS" name="EmojiKeyboardView.ICS"
parent="KeyboardView.ICS" parent="KeyboardView.ICS"

View File

@ -39,7 +39,7 @@
</case> </case>
<default> <default>
<Key <Key
latin:keyStyle="smileyKeyStyle" /> latin:keyStyle="emojiKeyStyle" />
</default> </default>
</switch> </switch>
</merge> </merge>

View File

@ -123,7 +123,8 @@
latin:styleName="emojiKeyStyle" latin:styleName="emojiKeyStyle"
latin:code="!code/key_emoji" latin:code="!code/key_emoji"
latin:keyIcon="!icon/emoji_key" latin:keyIcon="!icon/emoji_key"
latin:keyActionFlags="noKeyPreview" /> latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style <key-style
latin:styleName="settingsKeyStyle" latin:styleName="settingsKeyStyle"
latin:code="!code/key_settings" latin:code="!code/key_settings"

View File

@ -113,7 +113,8 @@
latin:styleName="emojiKeyStyle" latin:styleName="emojiKeyStyle"
latin:code="!code/key_emoji" latin:code="!code/key_emoji"
latin:keyIcon="!icon/emoji_key" latin:keyIcon="!icon/emoji_key"
latin:keyActionFlags="noKeyPreview" /> latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style <key-style
latin:styleName="settingsKeyStyle" latin:styleName="settingsKeyStyle"
latin:code="!code/key_settings" latin:code="!code/key_settings"

View File

@ -67,30 +67,6 @@
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<include <include
latin:keyboardLayout="@xml/key_styles_enter" /> latin:keyboardLayout="@xml/key_styles_enter" />
<switch>
<!-- Shift + Enter in textMultiLine field. -->
<case
latin:isMultiLine="true"
latin:keyboardLayoutSetElement="alphabetManualShifted|alphabetShiftLockShifted"
>
<key-style
latin:styleName="enterKeyStyle"
latin:parentStyle="shiftEnterKeyStyle" />
</case>
<!-- Smiley in textShortMessage field.
Overrides common enter key style. -->
<case
latin:mode="im"
>
<key-style
latin:styleName="enterKeyStyle"
latin:keyLabel=":-)"
latin:keyOutputText=":-) "
latin:keyLabelFlags="hasPopupHint"
latin:moreKeys="!text/more_keys_for_smiley"
latin:backgroundType="functional" />
</case>
</switch>
<key-style <key-style
latin:styleName="spaceKeyStyle" latin:styleName="spaceKeyStyle"
latin:code="!code/key_space" latin:code="!code/key_space"
@ -129,7 +105,8 @@
latin:styleName="emojiKeyStyle" latin:styleName="emojiKeyStyle"
latin:code="!code/key_emoji" latin:code="!code/key_emoji"
latin:keyIcon="!icon/emoji_key" latin:keyIcon="!icon/emoji_key"
latin:keyActionFlags="noKeyPreview" /> latin:keyActionFlags="noKeyPreview"
latin:backgroundType="functional" />
<key-style <key-style
latin:styleName="tabKeyStyle" latin:styleName="tabKeyStyle"
latin:code="!code/key_tab" latin:code="!code/key_tab"

View File

@ -50,7 +50,7 @@
latin:keyboardLayout="@xml/key_symbols_period" latin:keyboardLayout="@xml/key_symbols_period"
latin:backgroundType="functional" /> latin:backgroundType="functional" />
<Key <Key
latin:keyStyle="enterKeyStyle" latin:keyStyle="emojiKeyStyle"
latin:keyWidth="fillRight" /> latin:keyWidth="fillRight" />
</Row> </Row>
</merge> </merge>

View File

@ -66,7 +66,9 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
private SharedPreferences mPrefs; private SharedPreferences mPrefs;
private InputView mCurrentInputView; private InputView mCurrentInputView;
private View mMainKeyboardFrame;
private MainKeyboardView mKeyboardView; private MainKeyboardView mKeyboardView;
private EmojiKeyboardView mEmojiKeyboardView;
private LatinIME mLatinIME; private LatinIME mLatinIME;
private Resources mResources; private Resources mResources;
@ -167,6 +169,8 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
} }
private void setKeyboard(final Keyboard keyboard) { private void setKeyboard(final Keyboard keyboard) {
// Make {@link MainKeyboardView} visible and hide {@link EmojiKeyboardView}.
setMainKeyboardFrame();
final MainKeyboardView keyboardView = mKeyboardView; final MainKeyboardView keyboardView = mKeyboardView;
final Keyboard oldKeyboard = keyboardView.getKeyboard(); final Keyboard oldKeyboard = keyboardView.getKeyboard();
keyboardView.setKeyboard(keyboard); keyboardView.setKeyboard(keyboard);
@ -253,6 +257,18 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS)); setKeyboard(mKeyboardLayoutSet.getKeyboard(KeyboardId.ELEMENT_SYMBOLS));
} }
private void setMainKeyboardFrame() {
mMainKeyboardFrame.setVisibility(View.VISIBLE);
mEmojiKeyboardView.setVisibility(View.GONE);
}
// Implements {@link KeyboardState.SwitchActions}.
@Override
public void setEmojiKeyboard() {
mMainKeyboardFrame.setVisibility(View.GONE);
mEmojiKeyboardView.setVisibility(View.VISIBLE);
}
// Implements {@link KeyboardState.SwitchActions}. // Implements {@link KeyboardState.SwitchActions}.
@Override @Override
public void requestUpdatingShiftState() { public void requestUpdatingShiftState() {
@ -304,10 +320,16 @@ public final class KeyboardSwitcher implements KeyboardState.SwitchActions {
setContextThemeWrapper(mLatinIME, mKeyboardTheme); setContextThemeWrapper(mLatinIME, mKeyboardTheme);
mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate( mCurrentInputView = (InputView)LayoutInflater.from(mThemeContext).inflate(
R.layout.input_view, null); R.layout.input_view, null);
mMainKeyboardFrame = mCurrentInputView.findViewById(R.id.main_keyboard_frame);
mEmojiKeyboardView = (EmojiKeyboardView)mCurrentInputView.findViewById(
R.id.emoji_keyboard_view);
mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view); mKeyboardView = (MainKeyboardView) mCurrentInputView.findViewById(R.id.keyboard_view);
mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled); mKeyboardView.setHardwareAcceleratedDrawingEnabled(isHardwareAcceleratedDrawingEnabled);
mKeyboardView.setKeyboardActionListener(mLatinIME); mKeyboardView.setKeyboardActionListener(mLatinIME);
mEmojiKeyboardView.setHardwareAcceleratedDrawingEnabled(
isHardwareAcceleratedDrawingEnabled);
mEmojiKeyboardView.setKeyboardActionListener(mLatinIME);
// This always needs to be set since the accessibility state can // This always needs to be set since the accessibility state can
// potentially change without the input view being re-created. // potentially change without the input view being re-created.

View File

@ -46,6 +46,7 @@ public final class KeyboardState {
public void setAlphabetShiftLockedKeyboard(); public void setAlphabetShiftLockedKeyboard();
public void setAlphabetShiftLockShiftedKeyboard(); public void setAlphabetShiftLockShiftedKeyboard();
public void setSymbolsKeyboard(); public void setSymbolsKeyboard();
public void setEmojiKeyboard();
/** /**
* Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}. * Request to call back {@link KeyboardState#onUpdateShiftState(int, int)}.
@ -71,7 +72,10 @@ public final class KeyboardState {
private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 5; private static final int SWITCH_STATE_MOMENTARY_ALPHA_SHIFT = 5;
private int mSwitchState = SWITCH_STATE_ALPHA; private int mSwitchState = SWITCH_STATE_ALPHA;
// TODO: Consolidate these two mode booleans into one integer to distinguish between alphabet,
// symbols, and emoji mode.
private boolean mIsAlphabetMode; private boolean mIsAlphabetMode;
private boolean mIsEmojiMode;
private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState(); private AlphabetShiftState mAlphabetShiftState = new AlphabetShiftState();
private boolean mPrevMainKeyboardWasShiftLocked; private boolean mPrevMainKeyboardWasShiftLocked;
private int mRecapitalizeMode; private int mRecapitalizeMode;
@ -86,6 +90,7 @@ public final class KeyboardState {
public boolean mIsValid; public boolean mIsValid;
public boolean mIsAlphabetMode; public boolean mIsAlphabetMode;
public boolean mIsAlphabetShiftLocked; public boolean mIsAlphabetShiftLocked;
public boolean mIsEmojiMode;
public int mShiftMode; public int mShiftMode;
@Override @Override
@ -94,6 +99,8 @@ public final class KeyboardState {
if (mIsAlphabetMode) { if (mIsAlphabetMode) {
if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED"; if (mIsAlphabetShiftLocked) return "ALPHABET_SHIFT_LOCKED";
return "ALPHABET_" + shiftModeToString(mShiftMode); return "ALPHABET_" + shiftModeToString(mShiftMode);
} else if (mIsEmojiMode) {
return "EMOJI";
} else { } else {
return "SYMBOLS"; return "SYMBOLS";
} }
@ -125,6 +132,7 @@ public final class KeyboardState {
public void onSaveKeyboardState() { public void onSaveKeyboardState() {
final SavedKeyboardState state = mSavedKeyboardState; final SavedKeyboardState state = mSavedKeyboardState;
state.mIsAlphabetMode = mIsAlphabetMode; state.mIsAlphabetMode = mIsAlphabetMode;
state.mIsEmojiMode = mIsEmojiMode;
if (mIsAlphabetMode) { if (mIsAlphabetMode) {
state.mIsAlphabetShiftLocked = mAlphabetShiftState.isShiftLocked(); state.mIsAlphabetShiftLocked = mAlphabetShiftState.isShiftLocked();
state.mShiftMode = mAlphabetShiftState.isAutomaticShifted() ? AUTOMATIC_SHIFT state.mShiftMode = mAlphabetShiftState.isAutomaticShifted() ? AUTOMATIC_SHIFT
@ -145,6 +153,8 @@ public final class KeyboardState {
} }
if (!state.mIsValid || state.mIsAlphabetMode) { if (!state.mIsValid || state.mIsAlphabetMode) {
setAlphabetKeyboard(); setAlphabetKeyboard();
} else if (state.mIsEmojiMode) {
setEmojiKeyboard();
} else { } else {
setSymbolsKeyboard(); setSymbolsKeyboard();
} }
@ -254,6 +264,7 @@ public final class KeyboardState {
mSwitchActions.setAlphabetKeyboard(); mSwitchActions.setAlphabetKeyboard();
mIsAlphabetMode = true; mIsAlphabetMode = true;
mIsEmojiMode = false;
mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE; mRecapitalizeMode = RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE;
mSwitchState = SWITCH_STATE_ALPHA; mSwitchState = SWITCH_STATE_ALPHA;
mSwitchActions.requestUpdatingShiftState(); mSwitchActions.requestUpdatingShiftState();
@ -270,6 +281,15 @@ public final class KeyboardState {
mSwitchState = SWITCH_STATE_SYMBOL_BEGIN; mSwitchState = SWITCH_STATE_SYMBOL_BEGIN;
} }
private void setEmojiKeyboard() {
if (DEBUG_ACTION) {
Log.d(TAG, "setEmojiKeyboard");
}
mIsAlphabetMode = false;
mIsEmojiMode = true;
mSwitchActions.setEmojiKeyboard();
}
public void onPressKey(final int code, final boolean isSinglePointer, final int autoCaps) { public void onPressKey(final int code, final boolean isSinglePointer, final int autoCaps) {
if (DEBUG_EVENT) { if (DEBUG_EVENT) {
Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code) Log.d(TAG, "onPressKey: code=" + Constants.printableCode(code)
@ -547,6 +567,8 @@ public final class KeyboardState {
// If the code is a letter, update keyboard shift state. // If the code is a letter, update keyboard shift state.
if (Constants.isLetterCode(code)) { if (Constants.isLetterCode(code)) {
updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE); updateAlphabetShiftState(autoCaps, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);
} else if (code == Constants.CODE_EMOJI) {
setEmojiKeyboard();
} }
} }

View File

@ -1532,7 +1532,8 @@ public class LatinIME extends InputMethodService implements KeyboardActionListen
handleLanguageSwitchKey(); handleLanguageSwitchKey();
break; break;
case Constants.CODE_EMOJI: case Constants.CODE_EMOJI:
// TODO: Implement emoji keyboard switch. // Note: Switching emoji keyboard is being handled in
// {@link KeyboardState#onCodeInput(int,int)}.
break; break;
case Constants.CODE_ENTER: case Constants.CODE_ENTER:
final EditorInfo editorInfo = getCurrentInputEditorInfo(); final EditorInfo editorInfo = getCurrentInputEditorInfo();

View File

@ -112,6 +112,11 @@ public class MockKeyboardSwitcher implements KeyboardState.SwitchActions {
mLayout = MockConstants.SYMBOLS; mLayout = MockConstants.SYMBOLS;
} }
@Override
public void setEmojiKeyboard() {
// Just ignore.
}
@Override @Override
public void requestUpdatingShiftState() { public void requestUpdatingShiftState() {
mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE); mState.onUpdateShiftState(mAutoCapsState, RecapitalizeStatus.NOT_A_RECAPITALIZE_MODE);