Android开发之解析微博内容当中的表情图片(emoji)
在最近的微博项目当中,遇到了一个问题,就是需要我们将服务器上面返回的表情图片解析出来。
服务器返回的是json数据,表情格式,例如:色的表情返回格式为 [se]
这时候,需要们将[se]解析出来,并且在相应的位置显示相应的表情图片
经过网上的长时间的查找资料之后,得出了结果。
ExpressionUtil.java
import java.lang.reflect.Field; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ImageSpan; import android.util.Log; public class ExpressionUtil { String zhengze = "\\[[\u4E00-\u9FA5a-zA-Z0-9]*\\]"; /** * 对spanableString进行正则判断,如果符合要求,则以表情图片代替 * * @param context * @param spannableString * @param patten * @param start * @throws SecurityException * @throws NoSuchFieldException * @throws NumberFormatException * @throws IllegalArgumentException * @throws IllegalAccessException */ public static void dealExpression(Context context, SpannableString spannableString, Pattern patten, int start) throws SecurityException, NoSuchFieldException, NumberFormatException, IllegalArgumentException, IllegalAccessException { Matcher matcher = patten.matcher(spannableString); while (matcher.find()) { String key = matcher.group(); if (matcher.start() < start) { continue; } Field field = R.drawable.class.getDeclaredField(key); int resId = Integer.parseInt(field.get(null).toString()); // 通过上面匹配得到的字符串来生成图片资源id if (resId != 0) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId); ImageSpan imageSpan = new ImageSpan(bitmap); // 通过图片资源id来得到bitmap,用一个ImageSpan来包装 int end = matcher.start() + key.length(); // 计算该图片名字的长度,也就是要替换的字符串的长度 spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); // 将该图片替换字符串中规定的位置中 if (end < spannableString.length()) { // 如果整个字符串还未验证完,则继续。。 dealExpression(context, spannableString, patten, end); } break; } } } /** * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断 * * @param context * @param str * @return */ public static SpannableString getExpressionString(Context context, String str, String zhengze) { SpannableString spannableString = new SpannableString(str); Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE); // 通过传入的正则表达式来生成一个pattern try { dealExpression(context, spannableString, sinaPatten, 0); } catch (Exception e) { Log.e("dealExpression", e.getMessage()); } return spannableString; } }
PhraseDO.java
/** * 表情id与描述文字对应的类 * **/ public class PhraseDO { int id; public int getId() { return id; } public void setId(int id) { this.id = id; } public String getTag() { return tag; } public void setTag(String tag) { this.tag = tag; } String tag; public PhraseDO(int id, String tag) { this.id = id; this.tag = tag; } }
PhraseUtil.java
import java.util.ArrayList; import android.content.Context; import android.graphics.drawable.Drawable; /*** * 根据传入的表情描述获取对应的Drawable的辅助类 * ****/ public class PhraseUtil { Context context; ArrayList<PhraseDO> lists; public PhraseUtil(Context context) { this.context = context; lists = new ArrayList<PhraseDO>(); lists.add(new PhraseDO(R.drawable.se, "[se]")); lists.add(new PhraseDO(R.drawable.circle_s_netcom, "[爱你]")); } public Drawable getDrawableByTag(String tag) { int id = 0; for (PhraseDO phrase : lists) { if (phrase.getTag().equals(tag)) { id = phrase.getId(); } } Drawable drawable = context.getResources().getDrawable(id); return drawable; } }
注意:
lists.add(new PhraseDO(R.drawable.se, "[se]"));
首先需要知道服务器返回的图片json格式,并且以相应的命名方式存储,比如服务器返回的[se] 那么这儿也应该是[se]。说白了就是与服务器一致
还有就是一定要保证服务器当中存在的图片,你本地资源文件夹下也有。即服务器返回的任何微博数据都能匹配到你本地图片。否则会包主函数异常。
上面都是一些工具类
下面是测试
MainActivity.java
import java.util.ArrayList; import java.util.HashMap; import java.util.Map; import java.util.regex.Matcher; import java.util.regex.Pattern; import android.app.Activity; import android.graphics.Color; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.text.Spannable; import android.text.SpannableString; import android.text.style.ForegroundColorSpan; import android.text.style.ImageSpan; import android.widget.TextView; public class MainActivity extends Activity { public TextView txt; final String START = "start"; final String END = "end"; final String PHRASE = "phrase"; final String TYPED = "type"; String str = ""; PhraseUtil phraseUtil; final String TOPIC = "#.+?#"; final String NAMEH = "@([\u4e00-\u9fa5A-Za-z0-9_]*)"; final String URLH = "http://.*"; final String EMUATION = "\\[[\u4E00-\u9FA5a-zA-Z0-9]*\\]"; // 表情例如:[调皮][爱你]等正则 // 这类文本的内容是不变的,而是标记对象可以被附加和分离。可变的文本 SpannableString spannableString; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); txt = (TextView) findViewById(R.id.tv); phraseUtil = new PhraseUtil(this); str = "#jone# 我的小小测试关于微博中的高亮呵呵呵#jone# 大家来 [se]看看啊@王璇 http://www.jone.cn"; spannableString = new SpannableString(str); heightLight(TOPIC, Color.BLUE); heightLight(NAMEH, Color.RED); heightLight(URLH, Color.GREEN); heightPurch(EMUATION); //spannableString = ExpressionUtil.getExpressionString(this, str, EMUATION); txt.setText(spannableString); } // 高亮文字信息 private void heightLight(String pattern, int color) { ArrayList<Map<String, String>> lists = getStartAndEnd(Pattern.compile(pattern)); for (Map<String, String> str : lists) { ForegroundColorSpan span = new ForegroundColorSpan(color); spannableString.setSpan(span, Integer.parseInt(str.get(START)), Integer.parseInt(str.get(END)), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); } } // 表情图像处理 private void heightPurch(String pattern) { ArrayList<Map<String, String>> lists = getStartAndEnd(Pattern.compile(pattern)); for (Map<String, String> str : lists) { Drawable drawable = phraseUtil.getDrawableByTag(str.get(PHRASE)); drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()); ImageSpan span = new ImageSpan(drawable); spannableString.setSpan(span, Integer.parseInt(str.get(START)), Integer.parseInt(str.get(END)), Spannable.SPAN_EXCLUSIVE_INCLUSIVE); } } private ArrayList<Map<String, String>> getStartAndEnd(Pattern pattern) { ArrayList<Map<String, String>> lists = new ArrayList<Map<String, String>>(0); Matcher matcher = pattern.matcher(str); while (matcher.find()) { Map<String, String> map = new HashMap<String, String>(0); map.put(START, matcher.start() + ""); map.put(END, matcher.end() + ""); map.put(PHRASE, matcher.group()); // 匹配表情 lists.add(map); } return lists; } }
最后添加相应的布局文件即可。

浙公网安备 33010602011771号