Emoji开源项目解读(一)系统表情

标签: android 移动
11170人阅读 评论(2) 收藏 举报
分类:

 

介绍

上一节,我们对PhotoView开源项目进行了剖析解读, 这一节呢, 我们说说Emoji表情,大家每天都在用的QQ,微信或者其他聊天工具都有这个。

在我接触到的Emoji中,大致可以分为两类:

 系统支持的Emoji图标

 自定义Emoji图标

 这一节我们讨论系统支持的Emoji图标,掌握了这类,自定义Emoji表情也就水到渠成了

功能特性

 常用系统Emoji图标展示

 EditorText图标展示

 TextView图标展示

 表情的删除、添加、替换


源码剖析

 代码目录结构

老规矩,先上代码结构图,有个总体的认识

样例

做一个插入表情的流程例子      

  setContentView(R.layout.activity_main);
        mEditEmojicon = (EditText) findViewById(R.id.editEmojicon);
        mTxtEmojicon = (TextView) findViewById(R.id.txtEmojicon);
        mEditEmojicon.addTextChangedListener(new TextWatcherAdapter() {
            @Override
            public void onTextChanged(CharSequence s, int start, int before, int count) {
                mTxtEmojicon.setText(s);
            }
        });
时序图


 好了,上面是表情变化的一个调用流程,基本流程就是EmojiconsFragment里面的图标点击事件或者返回事件,回调一下, 让客户端来调用EmojiconEditText增删表情,然后监听EmojiconEditText的文本变化事件,来设置EmojiconTextView的文本, 这里都用到了EmojiconHandler这个类,他是表情的逻辑核心处理类,表情的管理都在这了。 我们的重点也在这了。

 插入表情

我们看到在例子中是在回调方法中,调用的插入方法

    @Override
    public void onEmojiconClicked(Emojicon emojicon) {
        EmojiconsFragment.input(mEditEmojicon, emojicon);
}
然后跟进去看到
    public static void input(EditText editText, Emojicon emojicon) {
        if (editText == null || emojicon == null) {
            return;
        }
 
        int start = editText.getSelectionStart();
        int end = editText.getSelectionEnd();
        if (start < 0) {
            editText.append(emojicon.getEmoji());
        } else {
            editText.getText().replace(Math.min(start, end), Math.max(start, end), emojicon.getEmoji(), 0, emojicon.getEmoji().length());
        }
    }
这里看有没有选中文本或者有游标,如果没有就在后面加上表情就好了,如果有的话,就替换指定位置的文本。

  删除表情

看代码

    @Override
    public void onEmojiconBackspaceClicked(View v) {
        EmojiconsFragment.backspace(mEditEmojicon);
}
进去在看
    public static void backspace(EditText editText) {
        KeyEvent event = new KeyEvent(0, 0, 0, KeyEvent.KEYCODE_DEL, 0, 0, 0, 0, KeyEvent.KEYCODE_ENDCALL);
        editText.dispatchKeyEvent(event);
}
这里直接生成了一个删除的按键实例,让EditText执行,就行了。 代码比较简洁有效,为什么这样可以呢?别急,看下面慢慢说明。

 EmojiconEditText

然后,我们在来看看EmojiconEditText中,对于文字变化后的逻辑是怎么处理的?也是关键地方所在。

看代码
    @Override
    protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
        EmojiconHandler.addEmojis(getContext(), getText(), mEmojiconSize);
}
又是EmojiconHandler来做的处理,跟进去
    public static void addEmojis(Context context, Spannable text, int emojiSize) {
        int length = text.length();
        EmojiconSpan[] oldSpans = text.getSpans(0, length, EmojiconSpan.class);
        for (int i = 0; i < oldSpans.length; i++) {
            text.removeSpan(oldSpans[i]);
        }
 
        int skip;
        for (int i = 0; i < length; i += skip) {
//中间省略......
text.setSpan(new EmojiconSpan(context, icon, emojiSize), i, i + skip, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
总体思路是这样的,先删除Spannable中的样式,然后在解析表情,添加样式,在增删样式对象中我们看到了EmojiconSpan,这么个东东?它又是干啥的呢?

 EmojiconSpan

可能有的童靴对样式这些比较迷糊, 好的, 为了有一个清晰的认识, 我画了一个类图,可以很明了的知道他们的关系.


 看看EmojiconSpan在什么等级上面,其实和ImageSpan是一个级别的,一种样式而已,从上图也可以了解到真正的跟样式打交道的,也不是EditText而是Editable。这样设计,文本和样式是分离的,耦合度比较低,还是不错的。呵呵。

再来看看EmojiconSpan的重写方法

    public Drawable getDrawable() {
        if (mDrawable == null) {
            try {
                mDrawable = mContext.getResources().getDrawable(mResourceId);
                int size = mSize;
                mDrawable.setBounds(0, 0, size, size);
            } catch (Exception e) {
                // swallow
            }
        }
        return mDrawable;
}
那么在添加表情的时候,资源id是怎么来的呢?

大家在EmojiconHandler里面可以看到有两个属性集合,存放emojisoftbank表情的

    private static final SparseIntArray sEmojisMap = new SparseIntArray(846);
    private static final SparseIntArray sSoftbanksMap = new SparseIntArray(471);
然后在静态块中进行了初始化操作
    static {
        // People
        sEmojisMap.put(0x1f604, R.drawable.emoji_1f604);
        sEmojisMap.put(0x1f603, R.drawable.emoji_1f603);
//省略......
}
后面添加的值我们很容易理解,是资源id,前面的16进制数值Key是个什么东东呢?

这个值是随意定义的Key吗?这个还真不是,呵呵。经过查资料得知,这个还是有一套标准的。对,Emoji也是有标准的。

咱们来举个例子吧,阳光图标吧

对应代码

sEmojisMap.put(0x2600, R.drawable.emoji_2600);
sSoftbanksMap.put(0xe04a, R.drawable.emoji_2600);
大家找到对应关系了吗?对的,前面的是Symbol 标准,后面的是softbank标准,google都支持。

 删除表情再议

这个在系统emoji中,程序处理比较简单,直接给EmojiconEditText一个删除的按键事件就解决了,正如上面说的那样,为什么这样做可以呢?归根到底还是因为他是系统的emoji,系统本身就可以识别这个编码,他当做一个东东来处理了,就像一个文字字符一样,如果是自定义emoji就没那么简单了,需要自己进行单独处理,下一节将会接触到这个。

 好了,系统Emoji表情就说到这了,主要是EditText的操作,文本样式的应用,系统Emoji编码知识,小知识点还是蛮多的。后续大家如果还有什么问题,或者有不正确的地方, 可以提出来,共同探讨。

 

Github

https://github.com/rockerhieu/emojicon

 Emoji图标编码

http://www.unicode.org/~scherer/emoji4unicode/snapshot/full.html

查看评论

android开源框架emojicon,妈妈再也不用担心我没表情了

最近发现了一个emoji表情框架,在githubhttps://github.com/rockerhieu/emojicon中,图片多到不能自理,不过了解了实现原理之后基本可以根据自己需要修改或者自己...
  • recall2012
  • recall2012
  • 2015-07-21 18:10:51
  • 5900

Emojicon Android表情开发

先看一下最终的效果: 效果图还是不错的,实现的原理我就不一一称述了,只讲一下它的使用方法, 目录结构是这样的: 你只需要把emojiconlibrary 作为模块导入到项目中就可以了,然后...
  • langtuteng136
  • langtuteng136
  • 2016-03-10 17:41:57
  • 863

emojicon表情在数据库中的存取方法

emojicon表情在数据库中的存取方法emojicon表情在数据库中的存取方法 问题描述 问题原因 解决方案 更改数据库编码 转化为 softbank emoji 对unicode字符串进行加密解密...
  • Kodoo
  • Kodoo
  • 2015-09-18 16:50:28
  • 4639

iOS swift-emoji表情的显示

有时在项目开发的时候会要求加入一些表情,而大多数情况下emoji表情也会加入其中,但一般项目中给我的emoji表情都是一些16进制的字符串,例如:0x1f603 如果要将这些16进制的字符串显示成表情...
  • lincsdnnet
  • lincsdnnet
  • 2016-08-23 21:42:12
  • 537

深度学习的浅实践:开源软件/数据库实现表情识别(1)

大数据加深度学习背景下的计算机视觉使得图像检测和识别上了一个新台阶。随着计算和数据资源的进一步发展,面对一个新的任务,收集足够多的数据,人工精确标注,训练深度神经网络,这样一个流程似乎可以解决一部分实...
  • zhzhanp
  • zhzhanp
  • 2016-02-21 12:56:02
  • 5405

表情识别

算法: Haar-Like人脸检测,AAM人脸跟踪,AAMSVM 7类:Neutral, Happy, Surprise, Angry, Disgust, Fear, Sad...
  • qiansen
  • qiansen
  • 2014-08-09 15:28:12
  • 12101

keras系列︱人脸表情分类与识别:opencv人脸检测+Keras情绪分类(四)

人脸识别热门,表情识别更加。但是表情识别很难,因为人脸的微表情很多,本节介绍一种比较粗线条的表情分类与识别的办法。 Keras系列:keras系列︱Sequential与Model模型、keras基本...
  • sinat_26917383
  • sinat_26917383
  • 2017-06-06 18:42:44
  • 8516

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

1.Emoji在手机上的显示规则 使用的是枚举来标记表情类型,值,对应的图片id文字标记,字符标记 private DisplayRules(int type, int value, in...
  • lizubing1992
  • lizubing1992
  • 2015-07-29 18:17:18
  • 6026

聊天界面的制作(三)——表情列表发送功能

基本功能 1. 自定义标题栏。(标题栏不做任何功能) 2. 有左右发送按钮。(这个只能自己和自己聊天哦,所以有左右发送按钮)   (1)点击左边按钮发送按钮,在ListView的左侧显示。   ...
  • u011203602
  • u011203602
  • 2015-09-11 10:17:10
  • 1069

关于解析emoji表情EmojiconTextView控件与超链接解析标签的冲突

前几天碰上这样一个需求,需要TextView既能显示表情又能显示超链接(并解析标签显示标签),普通TextView解析超链接并显示标签是没问题,方法就是: setText(Html.fromHtm...
  • qq_24229973
  • qq_24229973
  • 2016-03-09 16:42:36
  • 872
    个人资料
    专栏达人
    等级:
    访问量: 21万+
    积分: 2362
    排名: 1万+
    博客专栏