关于安卓中经常用到的表情开发中的一点小问题
安卓中经常用到表情,通常是用spannablestring +imagespan实现的,这次开发中也是这样做,有一个类,例如ParseEmojiUtil,用正则表达式来解析表情,展示到聊天页面。
代码类似这样private static final String REGEX_STR = "\\[1f\\w{3}\\]|\\[\\w{4}\\]";
private static int end=0;
public static int width1;
private static Matrix matrix;
private static String key;
private static Map<String,Bitmap> emojiMap=new HashMap<String,Bitmap>();
public static void dealExpression(Context context, SpannableString spannableString, Pattern patten, int start)
throws Exception {
Matcher matcher = patten.matcher(spannableString.toString());
while (matcher.find()) {
try
{
//String key = matcher.group();
key = matcher.group();
Log.d("Key", key);
//if (matcher.start() < start) {
//continue;
//}
if(emojiMap.containsKey(key)){
Bitmap bitmap2=emojiMap.get(key);
ImageSpan imageSpan = new ImageSpan(bitmap2);
int startPos=end+matcher.start();
end =end+ matcher.start() + key.length();
spannableString.setSpan(imageSpan, startPos, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
//if (end < spannableString.length()) {
//dealExpression(context, spannableString, patten, end);
//}
//break;
matcher.reset();
matcher = patten.matcher(spannableString.toString().substring(end));
}else{
Field field = R.drawable.class.getDeclaredField("emoji_"
+ key.substring(key.indexOf("[") + 1, key.lastIndexOf("]")));
int resId = Integer.parseInt(field.get(null).toString());
if (resId != 0) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
matrix=new Matrix();
//鐠嬪啯鏆g悰銊﹀剰鐎逛粙鏆�
if(Math.abs(width1-480)<=Math.abs(width1-720)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-720)<=Math.abs(width1-768)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-768)<=Math.abs(width1-800)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-800)<=Math.abs(width1-1080)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-1080)<=Math.abs(width1-1200)){
matrix.postScale(dip2px(context,45)/(float)bitmap.getWidth(), dip2px(context,45)/(float)bitmap.getHeight());//闁俺绻�
}else{
matrix.postScale(dip2px(context,80)/(float)bitmap.getWidth(), dip2px(context,80)/(float)bitmap.getHeight());//闁俺绻�
}
Bitmap bitmap2=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),matrix,true);
if(!emojiMap.containsKey(key)){
emojiMap.put(key,bitmap2);
}
ImageSpan imageSpan = new ImageSpan(bitmap2);
if(!bitmap.isRecycled()){
bitmap.recycle();
}
int startPos=end+matcher.start();
end =end+ matcher.start() + key.length();
spannableString.setSpan(imageSpan, startPos, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
//if (end < spannableString.length()) {
//dealExpression(context, spannableString, patten, end);
//}
//break;
matcher.reset();
matcher = patten.matcher(spannableString.toString().substring(end));
};
}
}catch(OutOfMemoryError err){
try{
if(key!=null){
Log.d("Key", key);
//if (matcher.start() < start) {
//continue;
//}
Field field = R.drawable.class.getDeclaredField("emoji_"
+ key.substring(key.indexOf("[") + 1, key.lastIndexOf("]")));
int resId = Integer.parseInt(field.get(null).toString());
if (resId != 0) {
Bitmap bitmap = BitmapFactory.decodeResource(context.getResources(), resId);
matrix=new Matrix();
if(Math.abs(width1-480)<=Math.abs(width1-720)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-720)<=Math.abs(width1-768)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-768)<=Math.abs(width1-800)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-800)<=Math.abs(width1-1080)){
matrix.postScale(dip2px(context,28)/(float)bitmap.getWidth(), dip2px(context,28)/(float)bitmap.getHeight());//闁俺绻�
}else if(Math.abs(width1-1080)<=Math.abs(width1-1200)){
matrix.postScale(dip2px(context,45)/(float)bitmap.getWidth(), dip2px(context,45)/(float)bitmap.getHeight());//闁俺绻�
}else{
matrix.postScale(dip2px(context,80)/(float)bitmap.getWidth(), dip2px(context,80)/(float)bitmap.getHeight());//闁俺绻�
}
Bitmap bitmap2=Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(), bitmap.getHeight(),matrix,true);
ImageSpan imageSpan = new ImageSpan(bitmap2);
if(!bitmap.isRecycled()){
bitmap.recycle();
}
int startPos=end+matcher.start();
end =end+ matcher.start() + key.length();
spannableString.setSpan(imageSpan, startPos, end, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
//if (end < spannableString.length()) {
//dealExpression(context, spannableString, patten, end);
//}
//break;
matcher.reset();
matcher = patten.matcher(spannableString.toString().substring(end));
};
}
}catch(OutOfMemoryError err1){
}
}
}
end=0;
}
当然catch outofmemoryerror里面的代码可以不去关注
值得记录有几点
1.matcher
matcher.find 找出一个匹配后,要reset,继续找下一个,
2.有些bitmap确认没用后,要记得显示回收,显示调用recycle
3.另外,当时做的时候如果解析很多表情,在个别机子上会报OOM的异常,
可以用一个全局变量map,保存资源id 以及对应的bitmap。
OOM的问题在安卓开发中,不小心就会遇到,碰到了要查内存溢出的原因,总结经验。