在上一篇随笔中记录了在微博正文的TextView中高亮部分关键字(@人名、#话题#和http短链接)的方法,这次的笔记记录如何实现表情功能,并把TextView中的[表情]转换成图片表情
目前比较流行的有两种方法:
第一种是调用新浪提供的API:https://api.weibo.com/2/emotions.json 通过icon或者url字段把表情图片download下来,接着对富文本进行转换。
第二种是把表情图片都下载到本地,直接放入drawable资源文件夹里,通过phrase和表情名字(与down下来的图片名字要一致)的对应进行转换。
为了效率的缘故,本项目采用第二种。至于怎么下载图片不详细展开,此次笔记着重于富文本与表情图片的转换在微博项目中的应用。
1 /** 2 * 高亮部分文本与表情的转换 3 * 4 * @param content 5 * 文本内容 6 * @return 7 */ 8 public static SpannableString setTextHighLightAndTxtToImg(String content, 9 Context context) { 10 SpannableString result = new SpannableString(content); 11 12 //高亮文本部分代码省略 13 14 if(content.contains("[")&&content.contains("]")){ 15 Pattern p = Pattern.compile(Constants.regex_emoji); 16 Matcher m = p.matcher(result); 17 while(m.find()){ 18 int start = m.start(); 19 int end = m.end(); 20 String phrase = content.substring(start, end); 21 String imageName = ""; 22 List<Emotions> list = MainActivity.emotionList; 23 for (Emotions emotions : list) { 24 if (emotions.getPhrase().equals(phrase)) { 25 imageName = emotions.getImageName(); 26 } 27 } 28 try { 29 Field f = (Field) R.drawable.class 30 .getDeclaredField(imageName); 31 int i = f.getInt(R.drawable.class); 32 Drawable drawable = context.getResources().getDrawable(i); 33 if (drawable != null) { 34 drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), 35 drawable.getIntrinsicHeight()); 36 ImageSpan span = new ImageSpan(drawable, 37 ImageSpan.ALIGN_BASELINE); 38 result.setSpan(span, start, end, 39 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); 40 } 41 } catch (SecurityException e) { 42 e.printStackTrace(); 43 } catch (NoSuchFieldException e) { 44 e.printStackTrace(); 45 } catch (IllegalArgumentException e) { 46 e.printStackTrace(); 47 } catch (IllegalAccessException e) { 48 } 49 50 } 51 52 } 53 54 return result; 55 }
算法思想:TextView中的[xxx]编码用正则表达式遍历出来,每一个编码都与MainActivity.emotionList中的每一个Emotions实例的phrase字段进行对比,遇到相同的则查找drawable中ImageName与phrase对应的表情图片,转换的具体函数用到
ImageSpan这个API。
其中MainActivity.emotionList这个List<Emotions>是Emotions实体类的列表,Emotions实体类则是根据2/emotions这个新浪官方表情接口的返回信息而设置的存储类。
Emotions的实体类如下
1 public class Emotions implements Serializable{ 2 3 /** 4 * 5 */ 6 private static final long serialVersionUID = 1L; 7 8 /** 表情使用的替代文字 */ 9 private String phrase; 10 /** 表情图片类型 */ 11 private String type; 12 /** 表情图片存放的位置 */ 13 private String url; 14 /** 是否为热门表情 */ 15 private String isHot; 16 /** 是否属于通用 */ 17 private String isCommon; 18 /** 表情分类 */ 19 private String category; 20 /** 表情名称 */ 21 private String imageName; 22 23 public String getPhrase() { 24 return phrase; 25 } 26 27 public void setPhrase(String phrase) { 28 this.phrase = phrase; 29 } 30 31 public String getType() { 32 return type; 33 } 34 35 public void setType(String type) { 36 this.type = type; 37 } 38 39 public String getUrl() { 40 return url; 41 } 42 43 public void setUrl(String url) { 44 this.url = url; 45 } 46 47 public String getIsHot() { 48 return isHot; 49 } 50 51 public void setIsHot(String isHot) { 52 this.isHot = isHot; 53 } 54 55 public String getIsCommon() { 56 return isCommon; 57 } 58 59 public void setIsCommon(String isCommon) { 60 this.isCommon = isCommon; 61 } 62 63 public String getCategory() { 64 return category; 65 } 66 67 public void setCategory(String category) { 68 this.category = category; 69 } 70 71 public String getImageName() { 72 return imageName; 73 } 74 75 public void setImageName(String imageName) { 76 this.imageName = imageName; 77 } 78 79 }
至于MainActivity.emotionList怎么来的则如下
1 public static List<Emotions> emotionList = new ArrayList<Emotions>(); 2 3 /** 初始化表情列表 */ 4 private void initEmotionsList() { 5 String[] emotions_phrase = getResources().getStringArray( 6 R.array.emotions_phrase); 7 String[] emotions_imagename = getResources().getStringArray( 8 R.array.emotions_imagename); 9 Emotions emotions; 10 for (int i = 0; i < 72; i++) { 11 emotions = new Emotions(); 12 emotions.setImageName(emotions_imagename[i]); 13 emotions.setPhrase(emotions_phrase[i]); 14 emotionList.add(emotions); 15 } 16 }
关于R.array.emotions_phrase和R.array.emotions_imagename两个数组,只能自己去收集了少年
效果图过几天放上来,手机因为测试刷微博而没流量了
5.26补上效果图两张: