content: 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;
  	}
  }
  