package net.cgt.weixin.utils; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; import net.cgt.weixin.R; import net.cgt.weixin.domain.ChatEmoji; import android.content.Context; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.text.Spannable; import android.text.SpannableString; import android.text.TextUtils; import android.text.style.ImageSpan; /** * 表情转换工具 * * @author lijian * @date 2014-12-11 22:59:16 */ public class FaceConversionUtil { private static final String LOGTAG = LogUtil.makeLogTag(FaceConversionUtil.class); /** 每一页表情的个数 */ private int pageSize = 20; private static FaceConversionUtil mFaceConversionUtil; /** 保存于内存中的表情HashMap(key:[可爱]; value:emoji_1) */ private HashMap<String, String> mMap_emoji = new HashMap<String, String>(); /** 保存于内存中的表情集合 */ private List<ChatEmoji> mList_emoji = new ArrayList<ChatEmoji>(); /** 表情分页的结果集合 */ public List<List<ChatEmoji>> emojiLists = new ArrayList<List<ChatEmoji>>(); private FaceConversionUtil() { } public static FaceConversionUtil getInstace() { if (mFaceConversionUtil == null) { mFaceConversionUtil = new FaceConversionUtil(); } return mFaceConversionUtil; } /** * 得到一个SpanableString对象,通过传入的字符串,并进行正则判断<br> * 将特定字符转换成对应"表情" * * @param context 上下文 * @param str 要被匹配的字符串 * @return */ public SpannableString getExpressionString(Context context, String str) { SpannableString spannableString = new SpannableString(str); // 正则表达式匹配字符串里是否含有表情,如: 我好[开心]啊 String zhengze = "\\[[^\\]]+\\]"; // 通过传入的正则表达式来生成一个pattern Pattern sinaPatten = Pattern.compile(zhengze, Pattern.CASE_INSENSITIVE); try { dealExpression(context, spannableString, sinaPatten, 0); } catch (Exception e) { L.e(LOGTAG, e.getMessage()); } return spannableString; } /** * 添加表情 * * @param context 上下文 * @param imgId * @param spannableString * @return */ public SpannableString addFace(Context context, int imgId, String spannableString) { if (TextUtils.isEmpty(spannableString)) { return null; } Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), imgId); bitmap = Bitmap.createScaledBitmap(bitmap, 48, 48, true); ImageSpan imageSpan = new ImageSpan(context, bitmap); SpannableString spannable = new SpannableString(spannableString); spannable.setSpan(imageSpan, 0, spannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); return spannable; } /** * 对spanableString进行正则判断,如果符合要求,则以表情图片代替 * * @param context 上下文 * @param spannableString 一个SpannableString对象 * @param patten 一个Pattern对象(正则) * @param start 起始位置 * @throws Exception */ private void dealExpression(Context context, SpannableString spannableString, Pattern patten, int start) throws Exception { Matcher matcher = patten.matcher(spannableString); while (matcher.find()) {//尝试查找与该模式匹配的输入序列的下一个子序列 String key = matcher.group();//返回由以前匹配操作所匹配的输入子序列 // 返回第一个字符的索引的文本匹配整个正则表达式,ture 则继续递归 if (matcher.start() < start) {//返回以前匹配的初始索引 continue; } String value = mMap_emoji.get(key); if (TextUtils.isEmpty(value)) { continue; } int resId = context.getResources().getIdentifier(value, "drawable", context.getPackageName()); // 通过上面匹配得到的字符串来生成图片资源id // Field field=R.drawable.class.getDeclaredField(value); // int resId=Integer.parseInt(field.get(null).toString()); if (resId != 0) { Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId); bitmap = Bitmap.createScaledBitmap(bitmap, DensityUtil.dip2px(context, 48), DensityUtil.dip2px(context, 48), true); // 通过图片资源id来得到bitmap,用一个ImageSpan来包装 ImageSpan imageSpan = new ImageSpan(bitmap); // 计算该图片名字的长度,也就是要替换的字符串的长度 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; } } } /** * 加载文本文件(表情清单文件) * * @param context */ public void getFileText(Context context) { ParseData(FileUtils.getEmojiFile(context), context); } /** * 解析字符 * * @param data */ private void ParseData(List<String> data, Context context) { if (data == null) { return; } ChatEmoji emoji; try { for (String str : data) { String[] text = str.split(","); String fileName = text[0].substring(0, text[0].lastIndexOf(".")); mMap_emoji.put(text[1], fileName); int resID = context.getResources().getIdentifier(fileName, "drawable", context.getPackageName()); if (resID != 0) { emoji = new ChatEmoji(); emoji.setId(resID); emoji.setDescription(text[1]);//可爱 emoji.setFaceName(fileName);//emoji_1 mList_emoji.add(emoji); } } //每页20个,总共能生成多少页 int pageCount = (int) Math.ceil(mList_emoji.size() / 20 + 0.1); for (int i = 0; i < pageCount; i++) { emojiLists.add(getData(i)); } } catch (Exception e) { e.printStackTrace(); L.e(LOGTAG, "ParseData--->" + e); } } /** * 获取分页数据 * * @param page * @return */ private List<ChatEmoji> getData(int page) { int startIndex = page * pageSize;//第page页的表情开始 int endIndex = startIndex + pageSize;//第page页的表情结束 //处理最后一页不足20个表情的问题,避免角标越界 if (endIndex > mList_emoji.size()) { endIndex = mList_emoji.size(); } // 不这么写,会在viewpager加载中报集合操作异常,我也不知道为什么 List<ChatEmoji> list = new ArrayList<ChatEmoji>(); list.addAll(mList_emoji.subList(startIndex, endIndex)); if (list.size() < pageSize) {//一页不足20个表情的,给其添加空表情对象,以凑齐20个 for (int i = list.size(); i < pageSize; i++) { ChatEmoji empty_ChatEmoji = new ChatEmoji(); list.add(empty_ChatEmoji); } } if (list.size() == pageSize) { ChatEmoji object = new ChatEmoji(); object.setId(R.drawable.cgt_selector_chat_emoji_del_bg); list.add(object); } return list; } }