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

最后添加相应的布局文件即可。

 

posted @ 2014-12-21 11:05  loneliness__白色  阅读(607)  评论(0)    收藏  举报