Android自定义表情功能的实现

Android开发中经常用到评论.回复.和发送聊天信息的功能开发,这其中就有表情的插入发送功能,经过长时间的开发总结,先封装出插入表情的功能实现代码开源给大家,共大家参考,共同学习进步:
1.拷贝表情图片资源到drawable其中的文件下,如图:
表情图片资源
2.编辑表情对应的文字(自定义名字,叫什么都可以),封装成arrays.xml文件,:

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android" xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">

    <string-array name="default_smiley_texts">
        <item>"[狗宝宝]"</item>
        <item>"[狗生日]"</item>
        <item>"[狗吃饭]"</item>
        <item>"[狗打针]"</item>
        <item>"[狗吠叫]"</item>
        <item>"[狗感冒]"</item>
        <item>"[狗怀孕]"</item>
        <item>"[狗满月]"</item>
        <item>"[狗牵手]"</item>
        <item>"[狗散步]"</item>
        <item>"[狗睡觉]"</item>
        <item>"[狗洗澡]"</item>
        <item>"[狗摇尾]"</item>
        <item>"[狗造型]"</item>
        <item>"[猫宝宝]"</item>
        <item>"[猫生日]"</item>
        <item>"[猫铲屎]"</item>
        <item>"[猫吃饭]"</item>
        <item>"[猫怀孕]"</item>
        <item>"[猫满月]"</item>
        <item>"[猫魔爪]"</item>
        <item>"[猫睡觉]"</item>
        <item>"[猫洗脸]"</item>
        <item>"[猫洗澡]"</item>
    </string-array>
  </resources>

3.封装表情和图片对应的类:

package com.pets.face;

import com.pets.activity.R;

/**
 * 表情图片和资源对照表
 * 
 * @author 孤狼
 * */
public class Expressions {

    public static int[] expressionImgs = new int[] {
            R.drawable.icon_dog_baobao, R.drawable.icon_dog_birth,
            R.drawable.icon_dog_chifan, R.drawable.icon_dog_dazhen,
            R.drawable.icon_dog_feijiao, R.drawable.icon_dog_ganmao,
            R.drawable.icon_dog_huaiyun, R.drawable.icon_dog_manyue,
            R.drawable.icon_dog_qianshou, R.drawable.icon_dog_sanbu,
            R.drawable.icon_dog_shuijiao, R.drawable.icon_dog_xizao,
            R.drawable.icon_dog_yaowei, R.drawable.icon_dog_zaoxing,
            R.drawable.icon_cat_baobao, R.drawable.icon_cat_birth,
            R.drawable.icon_cat_chanshi, R.drawable.icon_cat_chifan,
            R.drawable.icon_cat_huanyun, R.drawable.icon_cat_manyue,
            R.drawable.icon_cat_mozhao, R.drawable.icon_cat_shuijiao,
            R.drawable.icon_cat_xilian, R.drawable.icon_cat_xizao };
    public static String[] expressionImgNames = new String[] { "[狗宝宝]",
            "[狗生日]", "[狗吃饭]", "[狗打针]", "[狗吠叫]", "[狗感冒]", "[狗怀孕]", "[狗满月]",
            "[狗牵手]", "[狗散步]", "[狗睡觉]", "[狗洗澡]", "[狗摇尾]", "[狗造型]", "[猫宝宝]",
            "[猫生日]", "[猫铲屎]", "[猫吃饭]", "[猫怀孕]", "[猫满月]", "[猫魔爪]", "[猫睡觉]",
            "[猫洗脸]", "[猫洗澡]" };

    public static String[] replaceStrings(String[] str, String[] str2) {
        String newStr[] = new String[str.length - 1];
        for (int i = 0; i < str.length; i++) {
            newStr[i] = str[i].replace(str[i], str2[i]);
        }
        return newStr;
    }

}

4.构建工具类,使用正则表达式解析图文混排的内容:(容易错的是表情文字的数组长度和表情图片的数组长度不相等)

package com.pets.face;

import java.util.HashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.pets.activity.R;

import android.content.Context;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.style.ImageSpan;

/**
 * 正则表达式转换条目中图文混排的工具类
 * 
 * @author孤狼
 * @data 2014-12-19
 */

public class SmileyParser {
    /*
     * 单例模式 1文字资源,图片资源 2.使用正则表达式进行匹配文字 3.把edittext当中整体的内容匹配正则表达式一次
     * 4.SpannableStringBuilder 进行替换
     */
    private static SmileyParser sInstance;

    public static SmileyParser getInstance() {
        return sInstance;
    }

    public static void init(Context context) {
        sInstance = new SmileyParser(context);
    }

    private final Context mContext;
    private final String[] arrText;
    // 正则表达式
    private final Pattern mPattern;
    // String 图片字符串 Integer表情
    private final HashMap<String, Integer> mSmileyToRes;
    // arrays里面的表情内容
    public static final int DEFAULT_SMILEY_TEXTS = R.array.default_smiley_texts;

    private SmileyParser(Context context) {
        mContext = context;
        // 获取表情文字资源
        arrText = mContext.getResources().getStringArray(DEFAULT_SMILEY_TEXTS);
        // 获取表情ID与表情图标的Map
        mSmileyToRes = buildSmileyToRes();
        // 获取构建的正则表达式
        mPattern = buildPattern();
    }

    // 表情图片集合
    private static final int[] DEFAULT_SMILEY_RES_IDS = {
            R.drawable.icon_dog_baobao, R.drawable.icon_dog_birth,
            R.drawable.icon_dog_chifan, R.drawable.icon_dog_dazhen,
            R.drawable.icon_dog_feijiao, R.drawable.icon_dog_ganmao,
            R.drawable.icon_dog_huaiyun, R.drawable.icon_dog_manyue,
            R.drawable.icon_dog_qianshou, R.drawable.icon_dog_sanbu,
            R.drawable.icon_dog_shuijiao, R.drawable.icon_dog_xizao,
            R.drawable.icon_dog_yaowei, R.drawable.icon_dog_zaoxing,
            R.drawable.icon_cat_baobao, R.drawable.icon_cat_birth,
            R.drawable.icon_cat_chanshi, R.drawable.icon_cat_chifan,
            R.drawable.icon_cat_huanyun, R.drawable.icon_cat_manyue,
            R.drawable.icon_cat_mozhao, R.drawable.icon_cat_shuijiao,
            R.drawable.icon_cat_xilian, R.drawable.icon_cat_xizao };

    /**
     * 使用HashMap的key-value的形式来影射表情的ID和图片资源
     * 
     * @return
     */
    private HashMap<String, Integer> buildSmileyToRes() {
        if (DEFAULT_SMILEY_RES_IDS.length != arrText.length) {
            throw new IllegalStateException("ID和图片不匹配");
        }
        HashMap<String, Integer> smileyToRes = new HashMap<String, Integer>(
                arrText.length);
        for (int i = 0; i < arrText.length; i++) {
            // 图片名称作为key值,图片资源ID作为value值
            smileyToRes.put(arrText[i], DEFAULT_SMILEY_RES_IDS[i]);
        }
        return smileyToRes;
    }

    /**
     * 构建正则表达式,用来找到我们所要使用的图片
     * 
     * @return
     */
    private Pattern buildPattern() {
        StringBuilder patternString = new StringBuilder(arrText.length * 3);
        patternString.append('(');
        for (String s : arrText) {
            patternString.append(Pattern.quote(s));
            patternString.append('|');
        }
        patternString.replace(patternString.length() - 1,
                patternString.length(), ")");
        // 把String字符串编译成正则表达式()
        // ([调皮]|[调皮]|[调皮])
        return Pattern.compile(patternString.toString());
    }

    /**
     * 根据文本替换成图片
     * 
     * @param text
     *            对应表情
     * @return 一个表示图片的序列
     */
    public CharSequence addSmileySpans(CharSequence text) {
        // 把文字替换为对应图片
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        // 判断提取工具类(按照正则表达式)
        Matcher matcher = mPattern.matcher(text);
        while (matcher.find()) {
            // 获取对应表情的图片id
            int resId = mSmileyToRes.get(matcher.group());
            // 替换制定字符
            builder.setSpan(new ImageSpan(mContext, resId), matcher.start(),
                    matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        return builder;
    }
}

5.提供装载表情的控件,填充表情(要封装起来直接调用就行):

package com.pets.face;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.pets.activity.R;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ImageSpan;
import android.view.View;
import android.widget.AdapterView;
import android.widget.GridView;
import android.widget.SimpleAdapter;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.TextView;

/**
 * 填充装载表情的控件
 * 
 * @author孤狼
 * @since 2014-12-12
 * */
public class SmileyGrid {
    public static void initSimleGrid(final Activity activity,
            final int[] expressionImages1,
            final String[] expressionImageNames1, GridView gridView,
            final TextView content_et) {
        List<Map<String, Object>> listItems = new ArrayList<Map<String, Object>>();
        // 生成24个表情
        for (int i = 0; i < 24; i++) {
            Map<String, Object> listItem = new HashMap<String, Object>();
            listItem.put("image", expressionImages1[i]);
            listItems.add(listItem);
        }
        SimpleAdapter simpleAdapter = new SimpleAdapter(activity, listItems,
                R.layout.singleexpression, new String[] { "image" },
                new int[] { R.id.image });
        gridView.setAdapter(simpleAdapter);
        gridView.setOnItemClickListener(new OnItemClickListener() {
            @Override
            public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
                    long arg3) {
                Bitmap bitmap = null;
                bitmap = BitmapFactory.decodeResource(activity.getResources(),
                        expressionImages1[arg2 % expressionImages1.length]);
                int width = bitmap.getWidth();
                int height = bitmap.getHeight();
                Matrix matrix = new Matrix();
                // 缩放图片动作
                matrix.postScale(0.45f, 0.45f);
                Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0, width,
                        height, matrix, true);
                ImageSpan imageSpan = new ImageSpan(activity, resizedBitmap);
                SpannableString spannableString = new SpannableString(
                        expressionImageNames1[arg2].substring(0,
                                expressionImageNames1[arg2].length()));
                spannableString.setSpan(imageSpan, 0,
                        expressionImageNames1[arg2].length(),
                        Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
                // 编辑框设置数据
                content_et.append(spannableString);
            }
        });

    }
}

6.使用封装:

package com.pets.face;

import java.util.ArrayList;

import android.app.Activity;
import android.support.v4.view.ViewPager;
import android.support.v4.view.ViewPager.OnPageChangeListener;
import android.view.LayoutInflater;
import android.widget.GridView;
import android.widget.TextView;

import com.pets.activity.R;
import com.pets.customadapter.AdapterUtil;

/**
 * 表情显示
 * */
public class ShowFaceUtil {

    public static void showFace(final Activity activity, ViewPager viewPager,
            final TextView content_et) {
        // 引入表情
        final int[] expressionImages = Expressions.expressionImgs;
        final String[] expressionImageNames = Expressions.expressionImgNames;

        // 表情ViewPager
        LayoutInflater inflater = LayoutInflater.from(activity);
        ArrayList<GridView> grids = new ArrayList<GridView>();
        GridView gView1 = (GridView) inflater.inflate(R.layout.grid1, null);
        grids.add((GridView) gView1);

        SmileyGrid.initSimleGrid(activity, expressionImages,
                expressionImageNames, gView1, content_et);
        viewPager.setAdapter(AdapterUtil.getGridPager(grids));

    }
}

7.在Activity中直接调用ShowFaceUtil 的showFace()方法即可,传入ViewPager(大量的图片需要GridView滑动),TextView
好了,表情所需工具类全部封装完成,当调用ShowFaceUtil 的showFace()方法表情就会显示出来,那么从服务器获取的数据中含有表情,如何解析显示在界面上呢?细心的你会发现我们封装的SmileyParser 类中有个方法就是解析替换为表情图片的方法:

初始化// 设置详情,解析表情
 SmileyParser.init(activity);
 SmileyParser parser = SmileyParser.getInstance();
tv.setText(parser.addSmileySpans(item.getTi_details()));
就是SmileyParser的addSmileySpans(String string)方法

好了,全部完成,本文中的表情图片较少,详细更多的请看我的eoe论坛帖子
自定义表情

猜你喜欢

转载自blog.csdn.net/jackiandroid/article/details/44564697