解析emoji表情以及显示emoji表情

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文件

你可能感兴趣的:(emoji表情输入)