1.Emoji在手机上的显示规则
使用的是枚举来标记表情类型,值,对应的图片id文字标记,字符标记
private DisplayRules(int type, int value, int resId, String cls,
String remote) {
this.type = type;
this.emojiStr = cls;
this.value = value;
this.resId = resId;
this.remote = remote;
}
2.布局文件的显示
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emoji_title"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center_vertical"
android:layout_marginTop="7dp"
android:layout_marginBottom="7dp"
android:orientation="horizontal" >
<CheckBox
android:id="@+id/emoji_title_menu"
android:layout_width="24dp"
android:layout_height="24dp"
android:layout_marginLeft="15dp"
android:background="@drawable/selector_keyboard"
android:button="@null"
android:checked="false"
android:contentDescription="@null"
android:focusable="false" />
<RelativeLayout
android:layout_height="35dp"
android:layout_width="0dp"
android:layout_centerVertical="true"
android:layout_weight="1"
android:layout_marginLeft="@dimen/space_13"
android:background="@drawable/shape_commit_line"
>
<EditText
android:id="@+id/emoji_titile_input"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:layout_gravity="center_vertical"
android:paddingLeft="5dp"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_centerVertical="true"
android:background="@color/transparent"
android:hint="说点什么吧"
android:textSize="15sp" />
RelativeLayout>
<Button
android:id="@+id/emoji_title_send"
android:layout_width="65dp"
android:text="发送"
android:textColor="@color/white"
android:layout_height="33dp"
android:layout_marginLeft="10dp"
android:layout_marginRight="15dp"
android:textSize="@dimen/text_size_14"
android:contentDescription="@null"
android:background="@drawable/selector_btn_send" />
LinearLayout>
3.表情的显示fragment,很简单就是一个viewpager显示emoji图片
/**
* 表情页,每页的显示
*
*
*/
@SuppressLint("ValidFragment")
public class EmojiPageFragment extends Fragment {
private List datas;
private GridView sGrid;
private EmojiGridAdapter adapter;
private final OnEmojiClickListener listener;
public EmojiPageFragment(int index, int type, OnEmojiClickListener l) {
initData(index, type);
this.listener = l;
}
//初始化
private void initData(int index, int type) {
datas = new ArrayList();
if (KJEmojiFragment.EMOJI_TAB_CONTENT > 1) {
datas = DisplayRules.getAllByType(type);
} else {
List dataAll = DisplayRules.getAllByType(type);
int max = Math.min((index + 1) * KJEmojiConfig.COUNT_IN_PAGE,
dataAll.size());
for (int i = index * KJEmojiConfig.COUNT_IN_PAGE; i < max; i++) {
datas.add(dataAll.get(i));
}
//最后一个加上删除表情按钮
datas.add(new Emojicon(KJEmojiConfig.DELETE_EMOJI_ID, 1, "",
""));
}
}
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
sGrid = new GridView(getActivity());
sGrid.setNumColumns(KJEmojiConfig.COLUMNS);
adapter = new EmojiGridAdapter(getActivity(), datas);
sGrid.setAdapter(adapter);
sGrid.setOnItemClickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView> parent, View view,
int position, long id) {
EditText editText = (EditText) getActivity().findViewById(
R.id.emoji_titile_input);
if (listener != null) {
listener.onEmojiClick((Emojicon) parent.getAdapter()
.getItem(position));
}
InputHelper.input2OSC(editText, (Emojicon) parent.getAdapter()
.getItem(position));
if (position ==parent.getCount()-1 ) {
//最后一个的点击事件就是删除一个表情图标
InputHelper.backspace(editText);
}
}
});
sGrid.setSelector(new ColorDrawable(android.R.color.transparent));
return sGrid;
}
public GridView getRootView() {
return sGrid;
}
4.对于输入时的emoji表情的显示以及输入到特定的输入框,显示主要是构建spannable,Edittext和TextView就可以显示对应的spannable
/**
*
* @author kymjs (http://www.kymjs.com)
*/
public class InputHelper {
public static void backspace(EditText editText) {
if (editText == null) {
return;
}
KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0,
0, KeyEvent.KEYCODE_ENDCALL);
editText.dispatchKeyEvent(event);
}
/**
* 获取name对应的资源
*
* @param map
* @param name
* @return
*/
public static int getEmojiResId(String name) {
Integer res = DisplayRules.getMapAll().get(name);
if (res != null) {
return res.intValue();
} else {
return -1;
}
}
/**
* Support OSChina Client,due to the need to support both 2 Format
* (I'm drunk, I go home)
*/
public static Spannable displayEmoji(Resources res, CharSequence s) {
String str = s.toString();
Spannable spannable = null;
if (s instanceof Spannable) {
spannable = (Spannable) s;
} else {
// 构建文字span
spannable = new SpannableString(str);
}
for (int i = 0; i < str.length(); i++) {
int index1 = str.indexOf("[", i);
int length1 = str.indexOf("]", index1 + 1);
int index2 = str.indexOf(":", i);
int length2 = str.indexOf(":", index2 + 1);
int bound = (int) res.getDimension(R.dimen.space_20);
try {
String emojiStr = str.substring(index1, length1 + "]".length());
int resId = getEmojiResId(emojiStr);
if (resId > 0) {
// 构建图片span
Drawable drawable = res.getDrawable(resId);
drawable.setBounds(0, 20, bound, bound + 20);
ImageSpan span = new ImageSpan(drawable,
ImageSpan.ALIGN_BASELINE);
spannable.setSpan(span, index1, length1 + "]".length(),
Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
}
} catch (Exception e) {
}
return spannable;
}
public static void input2OSC(EditText editText, Emojicon emojicon) {
if (editText == null || emojicon == null) {
return;
}
int start = editText.getSelectionStart();
int end = editText.getSelectionEnd();
if (start < 0) {
// 没有多选时,直接在当前光标处添加
editText.append(displayEmoji(editText.getResources(),
emojicon.getRemote()));
} else {
// 将已选中的部分替换为表情(当长按文字时会多选刷中很多文字)
Spannable str = displayEmoji(editText.getResources(),
emojicon.getRemote());
editText.getText().replace(Math.min(start, end),
Math.max(start, end), str, 0, str.length());
}
}
}
5.最重要的是KJEmojiFragment
public class KJEmojiFragment extends Fragment implements
SoftKeyboardStateListener {
private LinearLayout mRootView;
private View mEmojiTitle;
private LinearLayout mEmojiContent;
private RadioGroup mEmojiBottom;
private View[] mEmojiTabs;
private EditText mEt;
private CheckBox mCBox;
private ViewPager mEmojiPager;
private EmojiPagerAdapter adapter;
private OnSendClickListener listener;
public static int EMOJI_TAB_CONTENT;
private IndicatorView mIndicator;
private SoftKeyboardStateHelper mKeyboardHelper;
private Button mSendBt;
@Override
public View onCreateView(LayoutInflater inflater,
ViewGroup container, Bundle savedInstanceState) {
super.onCreateView(inflater, container, savedInstanceState);
mRootView = (LinearLayout) inflater.inflate(R.layout.frag_main,
container, false);
initWidget(mRootView);
return mRootView;
}
public LinearLayout getRootView() {
return mRootView;
}
private void initWidget(View rootView) {
// title
mEmojiTitle = rootView.findViewById(R.id.emoji_title);
mEt = (EditText) mEmojiTitle.findViewById(R.id.emoji_titile_input);
mCBox = (CheckBox) mEmojiTitle.findViewById(R.id.emoji_title_menu);
mSendBt = (Button) mEmojiTitle.findViewById(R.id.emoji_title_send);
mCBox.setOnCheckedChangeListener(new OnCheckedChangeListener() {
@Override
public void onCheckedChanged(CompoundButton buttonView,
boolean isChecked) {
if (isChecked) {
showEmojiKeyBoard();
hideSoftKeyboard();
} else {
showSoftKeyboard();
}
}
});
mSendBt.setEnabled(false);
mEt.addTextChangedListener(new TextWatcher() {
private CharSequence temp;
@Override
public void afterTextChanged(Editable s) {
if(temp.length()>0){
mSendBt.setEnabled(true);
}else{
mSendBt.setEnabled(false);
}
}
@Override
public void beforeTextChanged(CharSequence s, int start, int count,
int after) {
}
@Override
public void onTextChanged(CharSequence s, int start, int before,
int count) {
temp = s;
}
});
// bottom
mEmojiBottom = (RadioGroup) rootView.findViewById(R.id.emoji_bottom);
EMOJI_TAB_CONTENT = 1;
mEmojiTabs = new View[EMOJI_TAB_CONTENT];
if (EMOJI_TAB_CONTENT <= 1) { // 只有一个分类的时候就不显示了
mEmojiBottom.setVisibility(View.GONE);
}
for (int i = 0; i < 1; i++) {
mEmojiTabs[i] = mEmojiBottom.getChildAt(i);
mEmojiTabs[i].setOnClickListener(getBottomBarClickListener(i));
}
mEmojiBottom.findViewById(R.id.emoji_bottom_del).setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
InputHelper.backspace(mEt);
}
});
// content必须放在bottom下面初始化
mEmojiContent = (LinearLayout) rootView
.findViewById(R.id.emoji_content);
mIndicator = new IndicatorView(UIUtils.getContext());
//设置点和点之间的间隙
mIndicator.setInterval(5);
//设置点的图片
mIndicator.setIndicatorDrawable(UIUtils.getDrawable(R.drawable.indicator_emoji));
LinearLayout.LayoutParams rl = new LinearLayout.LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.MATCH_PARENT);
rl.setMargins(0, 0, 20, 20);
mIndicator.setLayoutParams(rl);
mIndicator.setCount((DisplayRules.getAllByType(0).size() - 1 + KJEmojiConfig.COUNT_IN_PAGE)
/ KJEmojiConfig.COUNT_IN_PAGE);
mIndicator.setSelection(0);
mRootView.addView(mIndicator);
mIndicator.setVisibility(View.GONE);
mEmojiPager = (ViewPager) mEmojiContent.findViewById(R.id.emoji_pager);
adapter = new EmojiPagerAdapter(getFragmentManager());
mEmojiPager.setAdapter(adapter);
mEmojiPager.setOnPageChangeListener(new OnPageChangeListener() {
@Override
public void onPageSelected(int positon) {
mIndicator.setSelection(positon);
}
@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
}
@Override
public void onPageScrollStateChanged(int arg0) {
}
});
mKeyboardHelper = new SoftKeyboardStateHelper(getActivity().getWindow()
.getDecorView());
mKeyboardHelper.addSoftKeyboardStateListener(this);
if (getActivity() instanceof OnSendClickListener) {
listener = (OnSendClickListener) getActivity();
}
if (listener != null) {
mSendBt.setOnClickListener(
new OnClickListener() {
@Override
public void onClick(View v) {
listener.onClickSendButton(mEt.getText());
mEt.setHint("说点什么吧");
hideAllKeyBoard();
}
});
}
}
/**
* 底部栏点击事件监听器
*
* @param index
* @return
*/
private OnClickListener getBottomBarClickListener(final int index) {
return new OnClickListener() {
@Override
public void onClick(View v) {
mEmojiPager.setCurrentItem(index);
}
};
}
public void setOnSendClickListener(OnSendClickListener l) {
this.listener = l;
}
/******************************* preference *************************************/
public void clean() {
mEt.setText(null);
}
public void hideAllKeyBoard() {
hideEmojiKeyBoard();
hideSoftKeyboard();
}
/**
* 隐藏Emoji并显示软键盘
*/
public void hideEmojiKeyBoard() {
mEmojiBottom.setVisibility(View.GONE);
mEmojiContent.setVisibility(View.GONE);
mIndicator.setVisibility(View.GONE);
mCBox.setChecked(false);
}
/**
* 显示Emoji并隐藏软键盘
*/
public void showEmojiKeyBoard() {
mEmojiContent.setVisibility(View.VISIBLE);
if (EMOJI_TAB_CONTENT > 1) {
mEmojiBottom.setVisibility(View.VISIBLE);
}
mIndicator.setVisibility(View.VISIBLE);
mCBox.setChecked(true);
}
/**
* 隐藏软键盘
*/
public void hideSoftKeyboard() {
((InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE)).hideSoftInputFromWindow(
mEt.getWindowToken(), 0);
}
/**
* 显示软键盘
*/
public void showSoftKeyboard() {
mEt.requestFocus();
((InputMethodManager) getActivity().getSystemService(
Context.INPUT_METHOD_SERVICE)).showSoftInput(mEt,
InputMethodManager.SHOW_FORCED);
mIndicator.setVisibility(View.GONE);
}
public View getEmojiTitle() {
return mEmojiTitle;
}
public Editable getTextString() {
return mEt.getText();
}
public EditText getEditText() {
return mEt;
}
public boolean isShowEmojiKeyBoard() {
if (mCBox == null) {
return false;
} else {
return mCBox.isChecked();
}
}
/**
* 当软键盘显示时回调
*/
@Override
public void onSoftKeyboardOpened(int keyboardHeightInPx) {
if (mEmojiBottom != null && mEmojiContent != null) {
mEmojiBottom.setVisibility(View.GONE);
mEmojiContent.setVisibility(View.GONE);
}
if (mCBox != null) {
mCBox.setChecked(false);
}
}
public void hideFlagButton() {
if (mCBox != null) {
mCBox.setVisibility(View.GONE);
}
}
@Override
public void onSoftKeyboardClosed() {}
@Override
public void onStop() {
super.onStop();
hideSoftKeyboard();
}
}
6.这个是在开源中国新版的安卓app中的表情输入类,我根据自己的项目新增了一个viewpager的显示emoji表情,以及edittext的addTextChangedListener监听之后会有一个demo文件