Add EmojiKeyboardView
Bug: 6370846 Change-Id: Ic7d75f1d242795e756e6fede988cfe4b5cc17f0emain
parent
8e3a90e58f
commit
8ac0eb59e1
|
@ -0,0 +1,33 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2013, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/emoji_keyboard_scroller"
|
||||||
|
android:clipToPadding="false"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
<com.android.inputmethod.keyboard.internal.ScrollKeyboardView
|
||||||
|
android:id="@+id/emoji_keyboard_page"
|
||||||
|
android:layoutDirection="ltr"
|
||||||
|
android:layout_width="wrap_content"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
</com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2013, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<ImageView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
/>
|
|
@ -0,0 +1,26 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2013, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<TextView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="1.0"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:gravity="center"
|
||||||
|
/>
|
|
@ -0,0 +1,94 @@
|
||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<!--
|
||||||
|
/*
|
||||||
|
**
|
||||||
|
** Copyright 2013, 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.
|
||||||
|
*/
|
||||||
|
-->
|
||||||
|
|
||||||
|
<com.android.inputmethod.keyboard.EmojiKeyboardView
|
||||||
|
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:id="@+id/emoji_keyboard_view"
|
||||||
|
android:orientation="vertical"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
style="?attr/emojiKeyboardViewStyle"
|
||||||
|
>
|
||||||
|
<LinearLayout
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/suggestions_strip_height"
|
||||||
|
>
|
||||||
|
<TabHost
|
||||||
|
android:id="@+id/emoji_category_tabhost"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="87.5"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
>
|
||||||
|
<TabWidget
|
||||||
|
android:id="@android:id/tabs"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content"
|
||||||
|
android:background="@drawable/tab_selected"
|
||||||
|
android:divider="@null"
|
||||||
|
android:tabStripEnabled="true"
|
||||||
|
android:tabStripLeft="@drawable/tab_unselected"
|
||||||
|
android:tabStripRight="@drawable/tab_unselected" />
|
||||||
|
<FrameLayout
|
||||||
|
android:id="@android:id/tabcontent"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="0dip"
|
||||||
|
>
|
||||||
|
<!-- Empty placeholder that TabHost requires. But we don't use it to actually
|
||||||
|
display anything. We monitor the tab changes and change the ViewPager.
|
||||||
|
Similarly the ViewPager swipes are intercepted and passed to the TabHost. -->
|
||||||
|
<View
|
||||||
|
android:id="@+id/emoji_keyboard_dummy"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_height="0dip"
|
||||||
|
android:visibility="gone" />
|
||||||
|
</FrameLayout>
|
||||||
|
</TabHost>
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/emoji_keyboard_delete"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="12.5"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:src="@drawable/sym_keyboard_delete_holo" />
|
||||||
|
</LinearLayout>
|
||||||
|
<android.support.v4.view.ViewPager
|
||||||
|
android:id="@+id/emoji_keyboard_pager"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="wrap_content" />
|
||||||
|
<LinearLayout
|
||||||
|
android:id="@+id/emoji_action_bar"
|
||||||
|
android:orientation="horizontal"
|
||||||
|
android:layout_width="match_parent"
|
||||||
|
android:layout_height="@dimen/suggestions_strip_height"
|
||||||
|
>
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/emoji_keyboard_alphabet"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="0.825"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:src="@drawable/ic_ime_light" />
|
||||||
|
<ImageButton
|
||||||
|
android:id="@+id/emoji_keyboard_send"
|
||||||
|
android:layout_width="0dip"
|
||||||
|
android:layout_weight="0.125"
|
||||||
|
android:layout_height="match_parent"
|
||||||
|
android:src="@drawable/sym_keyboard_return_holo" />
|
||||||
|
</LinearLayout>
|
||||||
|
</com.android.inputmethod.keyboard.EmojiKeyboardView>
|
|
@ -22,6 +22,7 @@
|
||||||
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="90%p"
|
||||||
|
latin:keyLabelSize="60%p"
|
||||||
>
|
>
|
||||||
<GridRows
|
<GridRows
|
||||||
latin:textsArray="@array/emoji_emoticons"
|
latin:textsArray="@array/emoji_emoticons"
|
||||||
|
|
|
@ -22,6 +22,7 @@
|
||||||
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="90%p"
|
||||||
|
latin:keyLabelSize="60%p"
|
||||||
>
|
>
|
||||||
<GridRows
|
<GridRows
|
||||||
latin:codesArray="@array/emoji_recents"
|
latin:codesArray="@array/emoji_recents"
|
||||||
|
|
|
@ -0,0 +1,370 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013 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;
|
||||||
|
|
||||||
|
import static com.android.inputmethod.latin.Constants.NOT_A_COORDINATE;
|
||||||
|
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.res.ColorStateList;
|
||||||
|
import android.content.res.Resources;
|
||||||
|
import android.content.res.TypedArray;
|
||||||
|
import android.support.v4.view.PagerAdapter;
|
||||||
|
import android.support.v4.view.ViewPager;
|
||||||
|
import android.util.AttributeSet;
|
||||||
|
import android.util.SparseArray;
|
||||||
|
import android.view.LayoutInflater;
|
||||||
|
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.RecentsKeyboard;
|
||||||
|
import com.android.inputmethod.keyboard.internal.ScrollKeyboardView;
|
||||||
|
import com.android.inputmethod.keyboard.internal.ScrollViewWithNotifier;
|
||||||
|
import com.android.inputmethod.latin.Constants;
|
||||||
|
import com.android.inputmethod.latin.R;
|
||||||
|
import com.android.inputmethod.latin.SubtypeSwitcher;
|
||||||
|
import com.android.inputmethod.latin.utils.CollectionUtils;
|
||||||
|
import com.android.inputmethod.latin.utils.ResourceUtils;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* View class to implement Emoji keyboards.
|
||||||
|
* The Emoji keyboard consists of group of views {@link R.layout#emoji_keyboard_view}.
|
||||||
|
* <ol>
|
||||||
|
* <li> Emoji category tabs.
|
||||||
|
* <li> Delete button.
|
||||||
|
* <li> Emoji keyboard pages that can be scrolled by swiping horizontally or by selecting a tab.
|
||||||
|
* <li> Back to main keyboard button and enter button.
|
||||||
|
* </ol>
|
||||||
|
* Because of the above reasons, this class doesn't extend {@link KeyboardView}.
|
||||||
|
*/
|
||||||
|
public final class EmojiKeyboardView extends LinearLayout implements OnTabChangeListener,
|
||||||
|
ViewPager.OnPageChangeListener, View.OnClickListener,
|
||||||
|
ScrollKeyboardView.OnKeyClickListener {
|
||||||
|
private final int mKeyBackgroundId;
|
||||||
|
private final ColorStateList mTabLabelColor;
|
||||||
|
private final EmojiKeyboardAdapter mEmojiKeyboardAdapter;
|
||||||
|
|
||||||
|
private TabHost mTabHost;
|
||||||
|
private ViewPager mEmojiPager;
|
||||||
|
|
||||||
|
private KeyboardActionListener mKeyboardActionListener = KeyboardActionListener.EMPTY_LISTENER;
|
||||||
|
|
||||||
|
private int mCurrentCategory = CATEGORY_UNSPECIFIED;
|
||||||
|
private static final int CATEGORY_UNSPECIFIED = -1;
|
||||||
|
private static final int CATEGORY_RECENTS = 0;
|
||||||
|
private static final int CATEGORY_PEOPLE = 1;
|
||||||
|
private static final int CATEGORY_OBJECTS = 2;
|
||||||
|
private static final int CATEGORY_NATURE = 3;
|
||||||
|
private static final int CATEGORY_PLACES = 4;
|
||||||
|
private static final int CATEGORY_SYMBOLS = 5;
|
||||||
|
private static final int CATEGORY_EMOTICONS = 6;
|
||||||
|
private static final HashMap<String, Integer> sCategoryNameToIdMap =
|
||||||
|
CollectionUtils.newHashMap();
|
||||||
|
private static final String[] sCategoryName = {
|
||||||
|
"recents", "people", "objects", "nature", "places", "symbols", "emoticons"
|
||||||
|
};
|
||||||
|
private static final int[] sCategoryIcon = new int[] {
|
||||||
|
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[] 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,
|
||||||
|
};
|
||||||
|
|
||||||
|
public EmojiKeyboardView(final Context context, final AttributeSet attrs) {
|
||||||
|
this(context, attrs, R.attr.emojiKeyboardViewStyle);
|
||||||
|
}
|
||||||
|
|
||||||
|
public EmojiKeyboardView(final Context context, final AttributeSet attrs, final int defStyle) {
|
||||||
|
super(context, attrs, defStyle);
|
||||||
|
final TypedArray keyboardViewAttr = context.obtainStyledAttributes(attrs,
|
||||||
|
R.styleable.KeyboardView, defStyle, R.style.KeyboardView);
|
||||||
|
mKeyBackgroundId = keyboardViewAttr.getResourceId(
|
||||||
|
R.styleable.KeyboardView_keyBackground, 0);
|
||||||
|
keyboardViewAttr.recycle();
|
||||||
|
final TypedArray emojiKeyboardViewAttr = context.obtainStyledAttributes(attrs,
|
||||||
|
R.styleable.EmojiKeyboardView, defStyle, R.style.EmojiKeyboardView);
|
||||||
|
mTabLabelColor = emojiKeyboardViewAttr.getColorStateList(
|
||||||
|
R.styleable.EmojiKeyboardView_emojiTabLabelColor);
|
||||||
|
emojiKeyboardViewAttr.recycle();
|
||||||
|
final KeyboardLayoutSet.Builder builder = new KeyboardLayoutSet.Builder(
|
||||||
|
context, null /* editorInfo */);
|
||||||
|
final Resources res = context.getResources();
|
||||||
|
builder.setSubtype(SubtypeSwitcher.getInstance().getEmojiSubtype());
|
||||||
|
// TODO: Make Keyboard height variable.
|
||||||
|
builder.setKeyboardGeometry(ResourceUtils.getDefaultKeyboardWidth(res),
|
||||||
|
(int)(ResourceUtils.getDefaultKeyboardHeight(res)
|
||||||
|
- res.getDimension(R.dimen.suggestions_strip_height)));
|
||||||
|
builder.setOptions(false, false, false /* lanuageSwitchKeyEnabled */);
|
||||||
|
final KeyboardLayoutSet layoutSet = builder.build();
|
||||||
|
mEmojiKeyboardAdapter = new EmojiKeyboardAdapter(layoutSet, this);
|
||||||
|
// TODO: Save/restore recent keys from/to preferences.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onMeasure(final int widthMeasureSpec, final int heightMeasureSpec) {
|
||||||
|
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
|
||||||
|
final Resources res = getContext().getResources();
|
||||||
|
// The main keyboard expands to the entire this {@link KeyboardView}.
|
||||||
|
final int width = ResourceUtils.getDefaultKeyboardWidth(res)
|
||||||
|
+ getPaddingLeft() + getPaddingRight();
|
||||||
|
final int height = ResourceUtils.getDefaultKeyboardHeight(res)
|
||||||
|
+ res.getDimensionPixelSize(R.dimen.suggestions_strip_height)
|
||||||
|
+ getPaddingTop() + getPaddingBottom();
|
||||||
|
setMeasuredDimension(width, height);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void addTab(final TabHost host, final int category) {
|
||||||
|
final String tabId = sCategoryName[category];
|
||||||
|
sCategoryNameToIdMap.put(tabId, category);
|
||||||
|
final TabHost.TabSpec tspec = host.newTabSpec(tabId);
|
||||||
|
tspec.setContent(R.id.emoji_keyboard_dummy);
|
||||||
|
if (sCategoryIcon[category] != 0) {
|
||||||
|
final ImageView iconView = (ImageView)LayoutInflater.from(getContext()).inflate(
|
||||||
|
R.layout.emoji_keyboard_tab_icon, null);
|
||||||
|
iconView.setImageResource(sCategoryIcon[category]);
|
||||||
|
tspec.setIndicator(iconView);
|
||||||
|
}
|
||||||
|
if (sCategoryLabel[category] != null) {
|
||||||
|
final TextView textView = (TextView)LayoutInflater.from(getContext()).inflate(
|
||||||
|
R.layout.emoji_keyboard_tab_label, null);
|
||||||
|
textView.setText(sCategoryLabel[category]);
|
||||||
|
textView.setTextColor(mTabLabelColor);
|
||||||
|
textView.setBackgroundResource(mKeyBackgroundId);
|
||||||
|
tspec.setIndicator(textView);
|
||||||
|
}
|
||||||
|
host.addTab(tspec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void onFinishInflate() {
|
||||||
|
mTabHost = (TabHost)findViewById(R.id.emoji_category_tabhost);
|
||||||
|
mTabHost.setup();
|
||||||
|
addTab(mTabHost, CATEGORY_RECENTS);
|
||||||
|
addTab(mTabHost, CATEGORY_PEOPLE);
|
||||||
|
addTab(mTabHost, CATEGORY_OBJECTS);
|
||||||
|
addTab(mTabHost, CATEGORY_NATURE);
|
||||||
|
addTab(mTabHost, CATEGORY_PLACES);
|
||||||
|
addTab(mTabHost, CATEGORY_SYMBOLS);
|
||||||
|
addTab(mTabHost, CATEGORY_EMOTICONS);
|
||||||
|
mTabHost.setOnTabChangedListener(this);
|
||||||
|
mTabHost.getTabWidget().setStripEnabled(true);
|
||||||
|
|
||||||
|
mEmojiPager = (ViewPager)findViewById(R.id.emoji_keyboard_pager);
|
||||||
|
mEmojiPager.setAdapter(mEmojiKeyboardAdapter);
|
||||||
|
mEmojiPager.setOnPageChangeListener(this);
|
||||||
|
mEmojiPager.setOffscreenPageLimit(0);
|
||||||
|
final ViewGroup.LayoutParams lp = mEmojiPager.getLayoutParams();
|
||||||
|
final Resources res = getResources();
|
||||||
|
lp.height = ResourceUtils.getDefaultKeyboardHeight(res)
|
||||||
|
- res.getDimensionPixelSize(R.dimen.suggestions_strip_height);
|
||||||
|
mEmojiPager.setLayoutParams(lp);
|
||||||
|
|
||||||
|
// TODO: Record current category.
|
||||||
|
final int category = CATEGORY_PEOPLE;
|
||||||
|
setCurrentCategory(category, true /* force */);
|
||||||
|
|
||||||
|
// TODO: Implement auto repeat, using View.OnTouchListener?
|
||||||
|
final View deleteKey = findViewById(R.id.emoji_keyboard_delete);
|
||||||
|
deleteKey.setBackgroundResource(mKeyBackgroundId);
|
||||||
|
deleteKey.setTag(Constants.CODE_DELETE);
|
||||||
|
deleteKey.setOnClickListener(this);
|
||||||
|
final View alphabetKey = findViewById(R.id.emoji_keyboard_alphabet);
|
||||||
|
alphabetKey.setBackgroundResource(mKeyBackgroundId);
|
||||||
|
alphabetKey.setTag(Constants.CODE_SWITCH_ALPHA_SYMBOL);
|
||||||
|
alphabetKey.setOnClickListener(this);
|
||||||
|
final View sendKey = findViewById(R.id.emoji_keyboard_send);
|
||||||
|
sendKey.setBackgroundResource(mKeyBackgroundId);
|
||||||
|
sendKey.setTag(Constants.CODE_ENTER);
|
||||||
|
sendKey.setOnClickListener(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onTabChanged(final String tabId) {
|
||||||
|
final int category = sCategoryNameToIdMap.get(tabId);
|
||||||
|
setCurrentCategory(category, false /* force */);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageSelected(final int position) {
|
||||||
|
setCurrentCategory(position, false /* force */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrollStateChanged(final int state) {
|
||||||
|
// Ignore this message. Only want the actual page selected.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onPageScrolled(final int position, final float positionOffset,
|
||||||
|
final int positionOffsetPixels) {
|
||||||
|
// Ignore this message. Only want the actual page selected.
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onClick(final View v) {
|
||||||
|
if (v.getTag() instanceof Integer) {
|
||||||
|
final int code = (Integer)v.getTag();
|
||||||
|
registerCode(code);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void registerCode(final int code) {
|
||||||
|
mKeyboardActionListener.onPressKey(code, 0 /* repeatCount */, true /* isSinglePointer */);
|
||||||
|
mKeyboardActionListener.onCodeInput(code, NOT_A_COORDINATE, NOT_A_COORDINATE);
|
||||||
|
mKeyboardActionListener.onReleaseKey(code, false /* withSliding */);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onKeyClick(final Key key) {
|
||||||
|
mEmojiKeyboardAdapter.addRecentKey(key);
|
||||||
|
final int code = key.getCode();
|
||||||
|
if (code == Constants.CODE_OUTPUT_TEXT) {
|
||||||
|
mKeyboardActionListener.onTextInput(key.getOutputText());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
registerCode(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setHardwareAcceleratedDrawingEnabled(final boolean enabled) {
|
||||||
|
// TODO:
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setKeyboardActionListener(final KeyboardActionListener listener) {
|
||||||
|
mKeyboardActionListener = listener;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void setCurrentCategory(final int category, final boolean force) {
|
||||||
|
if (mCurrentCategory == category && !force) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
mCurrentCategory = category;
|
||||||
|
if (force || mEmojiPager.getCurrentItem() != category) {
|
||||||
|
mEmojiPager.setCurrentItem(category, true /* smoothScroll */);
|
||||||
|
}
|
||||||
|
if (force || mTabHost.getCurrentTab() != category) {
|
||||||
|
mTabHost.setCurrentTab(category);
|
||||||
|
}
|
||||||
|
// TODO: Record current category
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class EmojiKeyboardAdapter extends PagerAdapter {
|
||||||
|
private final ScrollKeyboardView.OnKeyClickListener mListener;
|
||||||
|
private final KeyboardLayoutSet mLayoutSet;
|
||||||
|
private final RecentsKeyboard mRecentsKeyboard;
|
||||||
|
private final SparseArray<ScrollKeyboardView> mActiveKeyboardView =
|
||||||
|
CollectionUtils.newSparseArray();
|
||||||
|
private int mActivePosition = CATEGORY_UNSPECIFIED;
|
||||||
|
|
||||||
|
public EmojiKeyboardAdapter(final KeyboardLayoutSet layoutSet,
|
||||||
|
final ScrollKeyboardView.OnKeyClickListener listener) {
|
||||||
|
mListener = listener;
|
||||||
|
mLayoutSet = layoutSet;
|
||||||
|
mRecentsKeyboard = new RecentsKeyboard(
|
||||||
|
layoutSet.getKeyboard(KeyboardId.ELEMENT_EMOJI_RECENTS));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addRecentKey(final Key key) {
|
||||||
|
if (mActivePosition == CATEGORY_RECENTS) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
mRecentsKeyboard.addRecentKey(key);
|
||||||
|
final KeyboardView recentKeyboardView = mActiveKeyboardView.get(CATEGORY_RECENTS);
|
||||||
|
if (recentKeyboardView != null) {
|
||||||
|
recentKeyboardView.invalidateAllKeys();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int getCount() {
|
||||||
|
return sCategoryName.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void setPrimaryItem(final View container, final int position, final Object object) {
|
||||||
|
if (mActivePosition == position) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final ScrollKeyboardView oldKeyboardView = mActiveKeyboardView.get(mActivePosition);
|
||||||
|
if (oldKeyboardView != null) {
|
||||||
|
oldKeyboardView.releaseCurrentKey();
|
||||||
|
oldKeyboardView.deallocateMemory();
|
||||||
|
}
|
||||||
|
mActivePosition = position;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Object instantiateItem(final ViewGroup container, final int position) {
|
||||||
|
final int elementId = sCategoryElementId[position];
|
||||||
|
final Keyboard keyboard = (elementId == KeyboardId.ELEMENT_EMOJI_RECENTS)
|
||||||
|
? mRecentsKeyboard : mLayoutSet.getKeyboard(elementId);
|
||||||
|
final LayoutInflater inflater = LayoutInflater.from(container.getContext());
|
||||||
|
final View view = inflater.inflate(
|
||||||
|
R.layout.emoji_keyboard_page, container, false /* attachToRoot */);
|
||||||
|
final ScrollKeyboardView keyboardView = (ScrollKeyboardView)view.findViewById(
|
||||||
|
R.id.emoji_keyboard_page);
|
||||||
|
keyboardView.setKeyboard(keyboard);
|
||||||
|
keyboardView.setOnKeyClickListener(mListener);
|
||||||
|
final ScrollViewWithNotifier scrollView = (ScrollViewWithNotifier)view.findViewById(
|
||||||
|
R.id.emoji_keyboard_scroller);
|
||||||
|
keyboardView.setScrollView(scrollView);
|
||||||
|
container.addView(view);
|
||||||
|
mActiveKeyboardView.put(position, keyboardView);
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
@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) {
|
||||||
|
final ScrollKeyboardView keyboardView = mActiveKeyboardView.get(position);
|
||||||
|
if (keyboardView != null) {
|
||||||
|
keyboardView.deallocateMemory();
|
||||||
|
mActiveKeyboardView.remove(position);
|
||||||
|
}
|
||||||
|
container.removeView(keyboardView);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue