Android项目 匹配Text里面的Emoji 和 QQ表情

吐槽:第一次写博客,新手一枚。写这个博客为了共享一下资源,大家相互学习,最主要目的是抛砖引玉,引大婶指高见。

前言:需求是这样的,搞聊天,而且是在一个字库里面没有emoji的android系统里面搞。我收到的数据格式是这样的“我是新来的< emoji1f639 >”、”我是新来的[微笑]”。其中< emoji1f639 >和[微笑]就是表情了,所以需要匹配里面的emoji表情和QQ表情。

首先是显示Emoji

(emoji说白了就是一套统一的Unicode编码,每一个编码索引一个emoji表情。emoji(えもじ)是岛国圣斗士发明的,会日语所以读起来很有感觉。)

效果图(我一般比较喜欢先看图再看码):
先看图在看码

先看图在看码

首先是判断是否有emoji在消息里面,因为emoji只需要替换消息的内容,所以首先处理。这里使用正则表达式来处理,判断是否满足条件,然后将匹配到的内容add到容器里面。

 private boolean checkEmojiInText(String text){
        if(text == null && text.equals(""))return false;

        //正则:取<emoji 和 >之间的内容(包含<emoji 和 >)
        Pattern p = Pattern.compile("<emoji(.*?)>");
        Matcher matcher = p.matcher(text);
        while (matcher.find()) {
            emojiTabList.add(matcher.group());
        }

        if(emojiTabList.size() > 0){
            return true;
        }

        return false;
    }

上面方法如果返回ture,就证明有emoji躲在text里面,所以我们需要找出来它的位置并把它给替换成emoji编码。
emoji字符串转成16进制的int就得到Unicode了,然后用 0x1F639 替换掉之前的< emoji1f639>就可以了。

if(checkEmojiInText(message)){
            for(int i = 0; i < emojiTabList.size(); i++){
    
    
                String emojiTab = emojiTabList.get(i).replace("<emoji", "")
                        .replace(">", "")
                        .toUpperCase();
                //string to 16进制 int
                int code = Integer.valueOf(emojiTab, 16);
                //转换成emoji
                String emoji = String.valueOf(Character.toChars(code));
                message = message.replace(emojiTabList.get(i), emoji);
            }
            LogUtils.i("new message is " + message);
            emojiTabList.clear();
        }

上面说了,我是在一个没有emoji表情的世界里玩emoji的,自然我就需要emoji的字库啦。千辛万苦找到了几套emoji font ttf,有ios的、htc的、三星等等,有性趣的朋友可以在下面下。

你想要emoji font ttf , 就点我把

使用方法的话,很简单就是在引用放在assets里面的字库,然后textview setTypeface就可以了。

Typeface typeface = Typeface
        .createFromAsset(mContext.getResources().getAssets(), "ColorEmojiFont.ttf");
textView.setTypeface(typeface );

然后到QQ表情

QQ表情的话,我是放在emoji之后才处理,因为emoji只是替换内容,QQ表情的话要用到
SpannableString,所以我放在后面处理。最终返回的结果是返回SpannableString,才能显示QQ表情。

SpannableString使用的话,给你一个跳板(某个大婶的博客)
Android开发之TextView高级应用

效果图(先看图再看码):
啪啪啪

啪啪啪

首先先判断是否有QQ表情在消息里面,这里继续用上正则表达式,判断’[’ 和’]’里面出现字符的个数。如果出现1~3个之间,证明有可能是表情。因为还不能准确地确定,所以把有一个结果add到容器里面先,然后再匹配。

private boolean checkFaceInText(String text){
        if(text == null && text.equals(""))return false;

        //正则:以[开头, 以]结尾,中间至少出现一个字符,但是不能超过三个
        Pattern p = Pattern.compile("\\[.{1,3}?\\]");
        Matcher matcher = p.matcher(text);
        while (matcher.find()) {
            faceTabList.add(matcher.group());
            facePositionList.add(matcher.start());
        }

        if(faceTabList.size() > 0
                && facePositionList.size() > 0
                && faceTabList.size() == facePositionList.size()){
            return true;
        }

        return false;
    }

接着做一个准备工作,就是在assets里面的face_icon文件夹内将所有QQ表情图片匹配到容器里面,这里我匹配到三个容器,为什么呢?因为我喜欢。

 public void prepareChatFace(){
        if(mContext == null)return;

        if(oneStringList.size() == 0 && twoStringList.size() == 0 && threeStringList.size() == 0){
            try {
                InputStream inputStream = mContext.getResources().getAssets().open(ASSETS_FACE_FILE);
                BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream, "UTF-8"));
                String lineInfo = null;
                while ((lineInfo = bufferedReader.readLine()) != null) {
                    String[] infoContent = lineInfo.split(",");

                    FaceInfo faceInfo = new FaceInfo();
                    faceInfo.setFaceName(infoContent[1]);
                    faceInfo.setFaceResource(getImageFromAssetsFile(infoContent[0]));

                    //face tag lenght
                    int strLenght = infoContent[1].length();
                    switch (strLenght){
                        case 1:
                            oneStringList.add(faceInfo);
                            break;
                        case 2:
                            twoStringList.add(faceInfo);
                            break;
                        case 3:
                            threeStringList.add(faceInfo);
                            break;
                        default:
                            break;
                    }

                }
            } catch (IOException e) {
                LogUtils.e("get assets file exception. error: " + e.getMessage());
                e.printStackTrace();
            }

            LogUtils.i("prepare all chat face to assign list finish!");
        }
    }

这里有一个getImageFromAssetsFile 方法,是用来读取QQ表情的

private Bitmap getImageFromAssetsFile(String fileName) {
        if(mContext == null)return null;

        Bitmap image = null;
        AssetManager am = mContext.getResources().getAssets();
        try
        {
            InputStream is = am.open(ASSETS_FACE_RESOURCE_FLODER+ "/" + fileName + ".png");
            image = BitmapFactory.decodeStream(is);
            is.close();

            if(image != null){
                return image;
            }
        }
        catch (IOException e) {
            LogUtils.e("read face image exception, error: " + e.getMessage());
            e.printStackTrace();
        }

        return null;
    }

好啦好啦,继续继续。这里使用到SpannableString,将拿到的QQ表情放到ImageSpan里面,然后通过spannableString.setSpan把ImageSpan放到SpannableString里面,setSpan开始位置用indexOf得到,然后结束位置用开始位置加上分割出来的字符串长度就可以了。

//接着判断 face
        SpannableString spannableString = new SpannableString(message);
        if(checkFaceInText(message)){
            //准备工作
            prepareChatFace();

            for (int i = 0; i < faceTabList.size(); i++) {
                Bitmap res = findRelevantFace(faceTabList.get(i)
                        .replace("[", "")
                        .replace("]", ""));
                if (res == null) continue;

                ImageSpan imageSpan = new ImageSpan(mContext, res);
                int startPos = facePositionList.get(i);
                int endPos = startPos + faceTabList.get(i).length();

                spannableString.setSpan(imageSpan, startPos, endPos,
                        Spanned.SPAN_INCLUSIVE_INCLUSIVE);
            }
            faceTabList.clear();
            facePositionList.clear();
        }

这里有个findRelevantFace方法,作用是找到相应的QQ表情。

    private Bitmap findRelevantFace(String text){
        if(text == null && text.equals(""))return null;
        switch (text.length()){
            case 1:
                for(FaceInfo faceInfo : oneStringList){
                    if(faceInfo.getFaceName().equals(text)){
                        return faceInfo.getFaceResource();
                    }
                }
                break;
            case 2:
                for(FaceInfo faceInfo : twoStringList){
                    if(faceInfo.getFaceName().equals(text)){
                        return faceInfo.getFaceResource();
                    }
                }
                break;
            case 3:
                for(FaceInfo faceInfo : threeStringList){
                    if(faceInfo.getFaceName().equals(text)){
                        return faceInfo.getFaceResource();
                    }
                }
                break;
        }

        return null;
    }

好啦这样就大功告成啦!!!

总结

第一次写文章,有点乱,望见谅。错误之处请指出,相互学习。
其实还是省略了很多的,有性趣的朋友可以download我的demo看看, 就是一个很简单的demo。
demo size有点大,是as的。

download demo

下面是github地址
demo

猜你喜欢

转载自blog.csdn.net/yudan505/article/details/53669354
今日推荐