最近在一个项目中做即时通讯,涉及到emoji表情的发送。为了使iphone和Android表情一致,就不能单纯的使用emoji表情编码的方式。最后决定使用图片的方式,使用
SpannableString进行图文混排。下面是开发过程中的一个demo。
一、效果图
二、图片资源准备
三、布局文件只是一个简单的TextView
<TextView android:id="@+id/txt_content" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:textColor="#000000" />
四、MainActivity
import android.app.Activity; import android.os.Bundle; import android.text.SpannableString; import android.widget.TextView; import java.util.HashMap; import java.util.Map; public class MainActivity extends Activity { private TextView txt_content; private String testString = "[微笑]早上好,[撇嘴][色][发呆]晚上好"; private Map<String, String> fachMap = new HashMap<String, String>(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); initView(); initData(); } private void initView() { txt_content = (TextView)findViewById(R.id.txt_content); } private void initData(){ SpannableString txt = FaceUtil.getExpressionString(this,testString); txt_content.setText(txt); } }
五、FaceUtil.java图文混排的核心类,包含正则表达式判断表情,以及转化为SpannableString的核心方法。
public class FaceUtil { private static Map<String, String> faceMap = new HashMap<String, String>(); static { faceMap.put("[微笑]", "expression_1"); faceMap.put("[撇嘴]", "expression_2"); faceMap.put("[色]", "expression_3"); faceMap.put("[发呆]", "expression_4"); faceMap.put("[得意]", "expression_5"); faceMap.put("[流泪]", "expression_6"); faceMap.put("[害羞]", "expression_7"); faceMap.put("[闭嘴]", "expression_8"); } public static SpannableString getExpressionString(Context context, String text) { String rgFace = "\\[[^\\]]+\\]"; Pattern ptFace = Pattern.compile(rgFace, Pattern.CASE_INSENSITIVE); return dealExpression(context, text, ptFace, 0); } private static SpannableString dealExpression(Context context, String text, Pattern patten, int start) { SpannableString spannableString = new SpannableString(text); Matcher matcher = patten.matcher(spannableString); while (matcher.find()) { Log.e("FaceUtil","mact"); String key = matcher.group(); if (matcher.start() < start) { continue; } String value = faceMap.get(key); Log.e("FaceUtil","mact"+value); if (TextUtils.isEmpty(value)) { continue; } int resId = context.getResources().getIdentifier(value, "drawable", context.getPackageName()); Log.e("FaceUtil","mact"+resId); // 通过上面匹配得到的字符串来生成图片资源id if (resId != 0) { Drawable drawable = context.getResources().getDrawable(resId); drawable.setBounds(0, 0, DensityUtil.dip2px(context, 26), DensityUtil.dip2px(context, 26)); // 通过图片资源id来得到bitmap,用一个ImageSpan来包装 ImageSpan imageSpan = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM); // 计算该图片名字的长度,也就是要替换的字符串的长度 int end = matcher.start() + key.length(); // 将该图片替换字符串中规定的位置中 spannableString.setSpan(imageSpan, matcher.start(), end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE); } } return spannableString; } }
六、一个dp与px互相转化的工具类
public class DensityUtil { /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */ public static int dip2px(Context context, float dpValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (dpValue * scale + 0.5f); } /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */ public static int px2dip(Context context, float pxValue) { final float scale = context.getResources().getDisplayMetrics().density; return (int) (pxValue / scale + 0.5f); } }
附:全套的emoji表情资源 http://download.youkuaiyun.com/detail/lo_ser/9708414