完整的Android表情功能处理方案

Android表情功能处理方案概述

1.原理和实现思路

2.表情图片显示

3.表情面板

4.表情的输入框插入和删除

5.表情添加脚本

Android中表情功能,一般都不是用ImageView去设置图片实现的,表情一般会嵌套在文本之中,那么如何实现呢,这里就介绍一下其中的原理,此外还有相关功能的实现思路和具体代码。

先看下良心动态图

1.原理和思路

a.表情内容的数据格式
表情看上去是图片,但是在数据传输的时候本质上是一个特殊文本;
比如QQ表情就是一个 "/表情字母"的结构,比如害羞的表情就是/hx,呲牙就是/cy...;
微博里表情就是"[表情名字]"的接口,比如可爱的表情就是[可爱]等等...。

b.特殊文本显示图片的原理
需要用到安卓中的SpannableString拓展性字符串相关知识;
SpannableString可以让一段字符串在显示的时候,将其中某小段文字附着上其他内容;
附着的拓展内容可能是图片,或者是文字格式,比如加粗斜体等。

下面稍微展开介绍下SpannableString,会的可以跳过

常用的拓展内容包含有
BackgroundColorSpan 背景色
ClickableSpan 文本可点击,有点击事件
UnderlineSpan 下划线
ImageSpan 图片
StyleSpan 字体样式:粗体、斜体等
URLSpan 文本超链接
此外还有删除线,缩放大小等不同样式的拓展

用法

SpannableString spannableString = new SpannableString(source);
ImageSpan span = new ImageSpan(context, bitmap);
spannableString.setSpan(span, start, start + emojiStr.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );

解释下用法

首先将原String文字包装成拓展性文字SpannableString,再创建一个需要类型的Span对象,比如表情图片就是ImageSpan,然后利用SpannableString的setSpan方法,将span对象设置在对应位置。
start就是需要附着的内容的开始位置
end是需要附着的内容的开始位置
flag标志位,这里是最常用的EXCLUSIVE_EXCLUSIVE的表示span拓展文本不包含前后,

此外还有INCLUSIVE是包含的意思

举例说明下,原文字是"文章作者是大帅比",那我创建个粗体拓展内容,并且要将其附着到作者二字上让其变成粗体,那开始位置就是2,即第三个字;结束位置就是4,即第五个,然后按照"包头不包尾"原则,包含第三个字不包含第五个字,即处理的就是第三四俩字"作者",flag我们将其设为EXCLUSIVE_INCLUSIVE即不包含前包含后。

那最终显示的文字就是"文章作者是大帅比"
如果我们在附着内容及作者二字前面输入内容时,由于是EXCLUSIVE不包含,所以不会跟着变化
"文章boredream作者是大帅比"
如果我们在附着内容及作者二字后面输入内容时,由于是INCLUSIVE包含,新内容也会包含进效果
"文章作者boredream是大帅比"

c.特殊文字的匹配
知道要处理哪些特殊文本,怎么处理,还有一步是怎么把特殊文本从一段文字里挑出来,即获取到特殊本文的开始和结束位置,以及他的文字内容,这里就要用到正则去进行匹配获取了正则的规则就不细说了,介绍下表情这里的正则匹配。

2.表情图片显示

文字附着表情图片很简单,用SpannableString中的ImageSpan,难点在于正则部分的获取处理:

首先是正则的写法,根据需要自行编写规则,这里以微博表情为例String regex = "\\[[\u4e00-\u9fa5\\w]+\\]";

简单介绍下,最外面是方括号符号,要注意由于[]在正则中有特殊意义,所以需要用斜杠\转义一下(\本身也需要转义所以是俩\\),中间\u4e00-\u9fa5表示中文,\\w表示下划线的任意单词字符,+ 代表一个或者多个,那么这段正则就代表,匹配方括号内有一或多个文字和单词字符的文本。

然后去while循环匹配就可以了,用matcher.find获取到匹配的开始位置,作为setSpan的start值,用matcher.group方法获取到匹配规则的具体表情文字,end值则直接利用开始位置加上表情文字的长度即可。

贴上代码

public static SpannableString getEmotionContent( final Context context, final TextView tv, String source) {
 SpannableString spannableString = new SpannableString(source);
 Resources res = context.getResources();

 String regexEmotion = "\\[([\u4e00-\u9fa5\\w])+\\]" ;
 Pattern patternEmotion = Pattern. compile(regexEmotion);
 Matcher matcherEmotion = patternEmotion.matcher(spannableString);

 while (matcherEmotion.find()) {
  // 获取匹配到的具体字符
  String key = matcherEmotion.group();
  // 匹配字符串的开始位置
  int start = matcherEmotion.start();
  // 利用表情名字获取到对应的图片
  Integer imgRes = EmotionUtils. getImgByName(key);
  if (imgRes != null) {
   // 压缩表情图片
   int size = ( int) tv.getTextSize();
  Bitmap bitmap = BitmapFactory.decodeResource(res, imgRes);
  Bitmap scaleBitmap = Bitmap.createScaledBitmap(bitmap, size, size, true);

  ImageSpan span = new ImageSpan(context, scaleBitmap);
  spannableString.setSpan(span, start, start + key.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE );
  }
 }
 return spannableString;
}

基本思路前面提过了,图片处理的地方还要再说明下

表情如果直接获取资源文件里的图片,可能会过大,所以方法参数里传入了需要显示的文字控件,然后利用文字大小去将表情图片再压缩一下,其中,EmotionUtils类就不介绍了,里面就是一个map集合,key为表情名字,value为表情图片的resId,然后提供一个getImgByName的方法可以根据名字获取图片键值对需要一个个添加比较麻烦,我们会在最后介绍一个表情添加的脚本,方便快速导入图片资源。

3.表情面板

结构就是ViewPager提供多页滑动,每页都是一个GridView显示20个表情,末尾还有一个删除按钮;
ViewPager和GridView的基本使用方法就不介绍了,这里说明下其中的特殊处理;

a.每个GridView的大小设置
GridView会显示3行7列,共21个Item,为了让Item能大小合适,最好的方法是利用动态计算的方式设置宽高,因为屏幕宽度各有不同,其他的一些大小计算也要注意用dp值转换下获取对应的px再使用,保证适配问题。

思路是获取屏幕宽度,减去间隙距离,然后除以7算出每个Item需要的宽度,然后再乘以3加上需要的间隙,算出表情面板的高度,利用算出来的值去创建设置面板大小。

b.需要多少个GridView
一共有多少页呢,虽然表情大部分情况下总数是固定的,但是最好还是根据代码的方式算出来需要多少页,而非直接人去目测计算要多少个GridView。

思路是for循环全部的图片名字,这里利用map.keySet获取全部的键集合,每次循环都把图片名添加到一个集合中,然后进行判断,如果满20个了就作为一组表情,新建一个GridView设置上去,最后把所有表情生成的一个个GridView放到一个总view集合中,利用ViewPager显示。

c.GridView末尾删除键处理
适配器和点击事件中,都利用position判断,如果是最后一个就进行特殊的显示和点击处理。

这几部分的代码比较乱,但是没有什么新知识点,都是一些逻辑方面的内容,就不贴出来了。

4.表情的输入框插入和删除

实质上还是对表情对应的文本数据进行操作,这里最要注意的地方是输入框中的光标问题,输入框其实也是TextView的一种,显示和之前介绍的方法一样,但是动态的添加和删除就需要注意处理位置的问题了。

a.手动设置光标
新添加一个表情,应该是在输入框中当前光标的位置插入图片,所以首先要知道光标的位置获取这里可以用et.setSelectionStart方法;
还有一点,添加完表情以后,光标应该更新到新添加内容后面,而设置光标位置就要用et.setSelection(position)方法。

b.调用系统按钮事件自动处理
删除就比较简单了,这里直接调用系统的 Delete 按钮事件即可,让某个控件调用按钮事件的方法为et.displatchKeyEvent(new KeyEvent(action, code));其中action就是动作,用ACTION_DOWN按下动作就可以了,而code为按钮事件码,删除对应的就是KEYCODE_DEL。

5.表情添加脚本

以上,知识点就全部介绍完毕了,最后是福利时间。

表情少则几十,多则甚至上百~ 一个一个的根据名字设置对应表情键值对会各种痛苦,这里推荐编写脚本进行处理,也就是写段功能自动的生成所需代码;

这段就比较灵活了,需要根据不同需要编写脚本,所以主要是提供个思路然后以微博为例编写代码;

微博中表情是"[表情文字]",而表情图片名字则是"d_表情拼音"(此外还有其他的名字样式,比如h_或者emoji_等等,暂时不管,处理原理都差不多);

这里要先说明一下前提,必须要按照一定规则来才能进行这种半自动化的处理,如果表情干脆名字就是瞎起的,那就没辙了,如果是公司自己做应用的话,一定要让美工切图后导出的图片文件名按照套路出牌;

新浪微博中d_表情拼音这里就都是中文对应的拼音而非英文,且中文都是和[表情文字]一致的,比如害羞表情的文字就是[害羞],而图片名字就是d_haixiu。

那微博这里处理就可以按照套路来了
1) 打开微博原版客户端,把所有表情全部选中,然后发出来
2) 在日志里获取到这段图片对应的文字数据
3) 用表情文字规则对这段文字进行循环匹配
4) 每次循环的时候都,把匹配的表情名字转为拼音(pinyin4j等工具)
5) 把表情文字转成的拼音再拼成图片资源的名字(微博这里就是加个"d_"前缀)
6) 拼接map.put的代码
7) 循环完成后,打印出来全部的map.put代码,然后复制到我们的表情工具类中使用

贴上代码,脚本直接新建一个java的项目放在main函数里运行就可以了

public static void weiboEmoji() {
 StringBuilder sb = new StringBuilder();

 String names = "[羞羞哒甜馨][萌神奥莉][带着微博去旅行][爱红包][拍照][马到成功]→_→[呵呵][嘻嘻][哈哈][爱你][挖鼻屎][吃惊][晕][泪][馋嘴][抓狂][哼][可爱][怒][汗][害羞][睡觉][钱][偷笑][笑cry][doge][喵喵][酷][衰][闭嘴][鄙视][花心][鼓掌][悲伤][思考][生病][亲亲][怒骂][太开心]" +
   "[懒得理你][右哼哼][左哼哼][嘘][委屈][吐][可怜][打哈气][挤眼][失望][顶][疑问][困][感冒][拜拜][黑线][阴险][打脸][傻眼][互粉][心][伤心][猪头][熊猫][兔子]" ;

 String regexEmoji = "\\[([\u4e00-\u9fa5a-zA-Z0-9])+\\]" ;
 Pattern patternEmoji = Pattern. compile(regexEmoji);
 Matcher matcherEmoji = patternEmoji.matcher(names);

 CharacterParser parser = CharacterParser. getInstance();
 while (matcherEmoji.find()) { // 如果可以匹配到
  String key = matcherEmoji.group(); // 获取匹配到的具体字符

  String pinyinName = "d_" + parser.getSpelling(key).replace("[" , "" ).replace("]" , "" );
  sb.append( "emojiMap.put(\"" + key + "\", R.drawable." + pinyinName + ");\n" );
 }
 System. out.println(sb.toString());
}

运行结果,从控制台复制代码粘贴到项目里的工具类中即可

可能有的表情文件名就是不按套路来,比如新浪微博这里的笑哭的表情,文字就是[笑cry],而图片文件名是d_xiaoku,那么也没关系,你复制到项目中,如果图片资源匹配不上的话也会报错提示,进行对应修改即可。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • Android编程开发之EditText实现输入QQ表情图像的方法

    本文实例讲述了Android编程开发之EditText实现输入QQ表情图像的方法.分享给大家供大家参考,具体如下: 实现效果如下: 将QQ表情图像放到res下的drawable-hdpi文件夹下: 布局文件: <EditText android:id="@+id/edittext" android:layout_width="fill_parent" android:layout_height="wrap_content" android:

  • Android编程开发实现TextView显示表情图像和文字的方法

    本文实例讲述了Android编程开发实现TextView显示表情图像和文字的方法.分享给大家供大家参考,具体如下: 从这个案例中我们可以学到当我们美化图片美化界面的时候可以在某一区域输入图片和文字混搭信息,第三张图片按比例缩小,第四张图像有超链接 布局文件 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.andro

  • Android开发技巧之像QQ一样输入文字和表情图像

    EditText和TextView一样,也可以进行图文混排.所不同的是,TextView只用于显示图文混排效果,而EditText不仅可显示,也可混合输入文字和图像,让我们先回顾一下图5.2所示的QQ聊天输入框,在输入框中可以同时输入文字和表情图像.实际上,这种效果在Android SDK中只需要几行代码就可以实现.为了使读者更有学习的冲动,先来欣赏一下即将实现的效果,如图5.16所示. 图5.16 在EditText控件中输入文字和图像 为了实现这个程序,首先来准备一些要用到的素材,也就是要在

  • Android编程实现QQ表情的发送和接收完整实例(附源码)

    本文实例讲述了Android编程实现QQ表情的发送和接收.分享给大家供大家参考,具体如下: 在自己做一个聊天应用练习的时候,需要用到表情,于是就想着模仿一下QQ表情,图片资源完全copy的QQ.apk,解压就可以得到,这里不细说. 下面将该应用中的表情模块功能抽离出来,以便自己以后复习回顾.. 先看一下效果图: 首先进入界面:(完全仿照QQ) 点击一下上面的表情图标: 选择一些表情,输入一些文字混合: 点击发送: 可以看到文字和表情图片都一起显示出来了. 下面列出一些关键代码: 表情工具类Exp

  • android高仿微信表情输入与键盘输入代码(详细实现分析)

    表情与键盘的切换输入大部分IM都会需要到,之前自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个困扰了我些时间,不过所幸在Github(其代码整体结构很不错)并且在论坛上找些解决思路,再加上研究了好几个开源项目的代码,最后终于苦逼地整合出比较不错的实现效果(这里不仅给出了实现方案,还提供一个可拓展的fragment模板以便大家实现自己的表情包)代码我已进行另外的封装与拓展,大家需要其他表情的话只需要根据fragment模板实现自己的表情界面,然后根据工厂类获取即可,实现效果

  • 基于Android开发支持表情的实现详解

    最近项目需要支持表情,表情的添加和解析实现基本上是参照Android自身的SmileyParser,具体就不多讲了,直接贴上代码: 复制代码 代码如下: public class SmileyParser {private static SmileyParser sInstance = null; private Context mContext = null;private Pattern mPattern = null;private HashMap<String, Integer> mS

  • Android输入框添加emoje表情图标的实现代码

    前言 再次写聊天的时候才发现,代码积累是一件非常重要的事情,就如这篇博客的意图其实就是代码积累的目的,其实没什么难度,但是一件很琐碎的事情真的也需要时间去完成和调试,所以,获取你在写一个功能的时候会觉得并没有多难,但是如果可以最好把代码整理/积累下来. demo描述 demo的功能其实就是仿照微信的 聊天 emoje 选择,采用了 viewpager+gridView 的方案,不过有空我会补上 recyclerView 的方案,目前还是先把功能实现了再说.另外在 TextView 和 EditT

  • Android输入法与表情面板切换时的界面抖动问题解决方法

    昨天琢磨了下Android的输入法弹出模式,突然发现利用动态切换输入法的弹出模式可以解决输入法抖动的问题.具体是怎样的抖动呢?我们先看微博的反面教材. [具体表现为:表情面板与输入法面板高度不一致,从而导致弹出输入法(layout被挤压)时,同时又需要隐藏表情面板(layout被拉升),最终让界面产生了高度差抖动,所以在切换时明显会有不大好的抖动体验)] 使用了解决抖动的解决方案后,效果如下: [这样的方案明显比微博的切换更平滑] 老样子,先说思路.主要我们要用到两个输入法弹出模式,分别是:ad

  • Android自带emoji表情的使用方法详解

    什么是emoji表情 emoji表情是一种表情符号,在代码中它现在其实是一组遵循Unicode的编码,即每一个表情符号都对应了一个Unicode编码.更进一步说,emoji表情实际上是一组Unicode编码与一组表情描述之间的对应.注意,这里所说的不是表情图片,而是表情描述.那么图片的实现是由谁来负责的呢?图片是由各个系统或者软件针对统一的表情描述来各自实现的,他们都遵循统一的Unicode编码规范.也就是说Unicode编码其所对应的表情描述是统一的,是所有人都要共同遵守的一套标准或者规范,而

  • Android高仿微信表情输入与键盘输入详解

    最近公司在项目上要使用到表情与键盘的切换输入,自己实现了一个,还是存在些缺陷,比如说键盘与表情切换时出现跳闪问题,这个相当困扰我,不过所幸在Github(其中一个不错的开源项目,其代码整体结构很不错)并且在论坛上找些解决方案,再加上我也是研究了好多个开源项目的代码,最后才苦逼地整合出比较不错的实现效果,可以说跟微信基本一样(嘿嘿,只能说目前还没发现大Bug,若发现大家一起日后慢慢完善,这里我也只是给出了实现方案,拓展其他表情我并没有实现哈,不过代码中我实现了一个可拓展的fragment模板以便大

随机推荐