最近,自己利用空闲的时间写了一个基于xmpp协议的即时通讯小应用,目的是为了了解xmpp协议,另一方面也是提高自己,增加自己的代码量,毕竟自己平时写的东西不多。在聊天室中,想要添加表情,而手机键盘自带的表情好像没法用,所以自己写了一个表情框,用于输入表情。
基本思路:;利用SpannableString实现text的样式设置,我们知道span.setSpan()方法可以实现将string替换为图片的操作,那么我们只需要在输入文本的过程中,将表情转换为对应的特殊标记的字符串,在显示的时候利用正则表达式,捕获特殊字符串,转换为相应的图片操作,那么就可以轻松完成聊天发送表情了。下面贴出代码:
<pre name="code" class="java">/**
* 常量基类.
*/
public class Constants {
public static List<Integer> mTypeList = new ArrayList<>();
private static SparseArray<String> mExpressionArray = new SparseArray<>();
private static Map<String, Integer> mTypeMap = new HashMap<>();
static {
mTypeList.add(R.drawable.ee_1);
mTypeList.add(R.drawable.ee_10);
mTypeList.add(R.drawable.ee_11);
mTypeList.add(R.drawable.ee_12);
mTypeList.add(R.drawable.ee_13);
mTypeList.add(R.drawable.ee_14);
mTypeList.add(R.drawable.ee_15);
mTypeList.add(R.drawable.ee_16);
mTypeList.add(R.drawable.ee_17);
mTypeList.add(R.drawable.ee_18);
mTypeList.add(R.drawable.ee_19);
mTypeList.add(R.drawable.ee_2);
mTypeList.add(R.drawable.ee_20);
mTypeList.add(R.drawable.ee_21);
mTypeList.add(R.drawable.ee_22);
mTypeList.add(R.drawable.ee_23);
mTypeList.add(R.drawable.ee_24);
mTypeList.add(R.drawable.ee_25);
mTypeList.add(R.drawable.ee_26);
mTypeList.add(R.drawable.ee_27);
mTypeList.add(R.drawable.ee_28);
mTypeList.add(R.drawable.ee_29);
mTypeList.add(R.drawable.ee_3);
mTypeList.add(R.drawable.ee_30);
mTypeList.add(R.drawable.ee_31);
mTypeList.add(R.drawable.ee_32);
mTypeList.add(R.drawable.ee_33);
mTypeList.add(R.drawable.ee_34);
mTypeList.add(R.drawable.ee_35);
for (int i=0; i< mTypeList.size();i++){
StringBuffer expression = new StringBuffer();
expression.append("[exp").append(i).append("]");
mExpressionArray.append(mTypeList.get(i), expression.toString());
mTypeMap.put(expression.toString(), mTypeList.get(i));
}
}
/**
* 通过传入图片的资源id获取到表情图片的转义描述符.
*
* @param resId 资源id
* @return 表情描述符
*/
public static String getExpression(int resId) {
return mExpressionArray.get(resId);
}
/**
* 根据转义符获取图片id.
*
* @param express
* @return 图片资源id
*/
public static int getExpressionId(String express) {
return mTypeMap.get(express);
}
}
自定义一个继承于popwindow的view,用于装载表情,供选择。他的实现很简单,主要是利用gridview,栅格的方式来展示图片表情:
/**
* 表情栏.
*/
public class ExpressionGridView extends PopupWindow{
private Context mContext;
private List<Integer> mExpressionArray = Constants.mTypeList;
private View mContentView;
private int mScreenWidth;
private int mScreenHeight;
private GridView mGridView;
public ExpressionGridView(Context context){
mContext = context;
initScreen();
initContentView();
}
private void initContentView(){
setFocusable(true);
setWidth(mScreenWidth);
setOutsideTouchable(true);
setHeight(mScreenHeight);
setTouchable(true);
setBackgroundDrawable(new BitmapDrawable()); //这句话必须加,否则不能响应点击返回按钮
mContentView = LayoutInflater.from(mContext).inflate(R.layout.expression_gridview, null);
mGridView = (GridView) mContentView.findViewById(R.id.expression_grid);
mGridView.setCacheColorHint(Color.TRANSPARENT);
mGridView.setAdapter(new gridAdapter());
setContentView(mContentView);
}
public void show(){
showAtLocation(mContentView, Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
}
public void setGridItemOnclickListener(OnItemClickListener listener){
if(listener != null){
mGridView.setOnItemClickListener(listener);
}
}
private class gridAdapter extends BaseAdapter{
@Override
public int getCount() {
return mExpressionArray == null ? 0: mExpressionArray.size();
}
@Override
public Object getItem(int position) {
return mExpressionArray.get(position);
}
@Override
public long getItemId(int position) {
return position;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
ImageView image;
if(convertView == null){
convertView= LayoutInflater.from(mContext).inflate(R.layout.expression_gridview_item, null);
image = (ImageView) convertView.findViewById(R.id.expression_item_image);
} else {
image = (ImageView) convertView.findViewById(R.id.expression_item_image);
}
image.setImageResource(mExpressionArray.get(position));
return convertView;
}
}
private void initScreen(){
DisplayMetrics metrics = new DisplayMetrics();
((Activity)mContext).getWindowManager().getDefaultDisplay().getMetrics(metrics);
mScreenWidth = metrics.widthPixels;
mScreenHeight = metrics.heightPixels / 3;
}
}
接下来是整个实现过程的重点,利用正则表达式进行特殊字符串的匹配,然后进行相应图片的转换显示:具体看代码:
private void showExpressionWindow() {
mGridView = new ExpressionGridView(this);
mGridView.setGridItemOnclickListener(new OnItemClickListener() {
@Override
public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
int resource = (int) parent.getItemAtPosition(position);
String expression = Constants.getExpression(resource);
String message = mInput.getEditableText().toString();
StringBuffer buffer = new StringBuffer(message);
buffer.insert(mInput.getSelectionStart(), expression);
//进行正则表达式的匹配
String regex = "\\[exp[0-9][0-9]?\\]";// "\"也需要进行转义
Pattern pattern = Pattern.compile(regex);
Matcher matcher = pattern.matcher(buffer.toString());
SpannableString span = new SpannableString(buffer.toString());
while (matcher.find()) {
Drawable drawable = getResources().getDrawable(Constants.getExpressionId
(matcher.group()));
drawable.setBounds(0, 0, 40, 40); //这里必须要设置,否则图片不能显示出来
span.setSpan(new ImageSpan(drawable), matcher.start(), matcher.end(),
Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
mInput.setText(span);
mInput.setSelection(span.length());
mGridView.dismiss();
}
});
mGridView.show();
}
showExpressionWindow()方法实现了弹出选择框,选择表情之后再编辑栏中进行显示,那么在进行聊天时,还需要将发出的聊天消息在消息列表中进行显示,实现的过程大同小异,和上面的实现过程也是相同的,将特殊表情符转换成表情图片。具体的我就不在多说了,代码中已经写得很清楚了,水平有限,各位如果有社么意见,请多多指教。
<img src="https://img-blog.csdn.net/20150818233541614?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="" />