Android使用SpannableString实现文本框里插入表情

来源:互联网 发布:照片换底色软件 编辑:程序博客网 时间:2024/05/18 00:01
 

Android使用SpannableString实现文本框里插入表情

标签: Android开发表情
 660人阅读 评论(0) 收藏 举报
 分类:

效果

         

介绍

       SpannableString,相较于普通String带有丰富的格式设置,可使文本的可读性更强。两者都用于存储字符串,而SpannableString的特殊之处就在于有一个setSpan()函数,因而能给存储的文本添加各种样式,诸如文本颜色样式((ForgroundColorSpan),文本背景颜色样式((BackgroundColorSpan)下划线样式((UnderlineSpan)等,而今天我们的功能实现需要用到的则是图片样式(ImageSpan)。

       SpannableStringBuilder,类似于StringBuilder,可以通过其append()方法拼接多个String。而SpannableString则类似于String,构造对象对传入一个String,之后再也无法更改String的内容,也无法拼接多个SpannableString。

       相关API的类大致分层如下:

        由上图可看出,由于Spannable等最终都实现了CharSequence接口,所以可以直接将SpannableString和SpannableStringBuillder通过TextView.setText()方法设置给TextView。


实现

主要就是实现自定义控件类,然后覆写setText()方法

  1. package com.example.emodemo.view;  
  2.   
  3. import java.util.regex.Matcher;  
  4. import java.util.regex.Pattern;  
  5.   
  6. import android.content.Context;  
  7. import android.graphics.Bitmap;  
  8. import android.graphics.BitmapFactory;  
  9. import android.text.Spannable;  
  10. import android.text.SpannableString;  
  11. import android.text.TextUtils;  
  12. import android.text.style.ImageSpan;  
  13. import android.util.AttributeSet;  
  14. import android.widget.TextView;  
  15.   
  16. public class EmoticonsTextView extends TextView {  
  17.   
  18.     public EmoticonsTextView(Context context) {  
  19.         super(context);  
  20.     }  
  21.   
  22.     public EmoticonsTextView(Context context, AttributeSet attrs, int defStyle) {  
  23.         super(context, attrs, defStyle);  
  24.     }  
  25.   
  26.     public EmoticonsTextView(Context context, AttributeSet attrs) {  
  27.         super(context, attrs);  
  28.     }  
  29.   
  30.     @Override  
  31.     public void setText(CharSequence text, BufferType type) {  
  32.         if (!TextUtils.isEmpty(text)) {  
  33.             super.setText(replace(text.toString()), type);  
  34.         } else {  
  35.             super.setText(text, type);  
  36.         }  
  37.     }  
  38.   
  39.     private Pattern buildPattern() {  
  40.         return Pattern.compile("\\[f[0-9]{3}]", Pattern.CASE_INSENSITIVE);  
  41.     }  
  42.   
  43.     private CharSequence replace(String text) {  
  44.         try {  
  45.             SpannableString spannableString = new SpannableString(text);  
  46.             int start = 0;  
  47.             Pattern pattern = buildPattern();  
  48.             Matcher matcher = pattern.matcher(text);  
  49.             while (matcher.find()) {  
  50.                 String faceText = matcher.group();  
  51.                 String key = faceText.substring(1);  
  52.                 key = key.substring(key.indexOf("[")+1, key.indexOf("]"));  
  53.                 BitmapFactory.Options options = new BitmapFactory.Options();  
  54.                 Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),  
  55.                         getContext().getResources().getIdentifier(key, "drawable", getContext().getPackageName()), options);  
  56.                 ImageSpan imageSpan = new ImageSpan(getContext(), bitmap);  
  57.                 int startIndex = text.indexOf(faceText, start);  
  58.                 int endIndex = startIndex + faceText.length();  
  59.                 if (startIndex >= 0)  
  60.                     spannableString.setSpan(imageSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);  
  61.                 start = (endIndex - 1);  
  62.             }  
  63.             return spannableString;  
  64.         } catch (Exception e) {  
  65.             return text;  
  66.         }  
  67.     }  
  68. }  
这里重点解析replace(String text)方法:

1.

  1. SpannableString spannableString = new SpannableString(text);  

构建SpannableString对象,传入一个String(可以是纯文本,可以是表情代码,也可以是文本和表情代码混合);

2.

  1. Pattern pattern = buildPattern();  
  2. private Pattern buildPattern() {  
  3.         return Pattern.compile("\\[f[0-9]{3}]", Pattern.CASE_INSENSITIVE);  
  4.     }  

将给定的正则表达式编译并赋予给Pattern类。这里你可以理解为制定了表情代码的正则表达式,文本中符合这个正则表达式的都是表情代码,即制定了一个筛选规则,用于筛选出文本中的表情代码。

这里的正则表达式含义为[f(连续三位0-9的整数)],如[f001],[f002],[f003]等。

3.

  1. Matcher matcher = pattern.matcher(text);  

 生成一个给定命名的Matcher对象。你可以把这段代码理解为,是将上面制定的筛选规则输入了一台筛选机器,然后等待筛选。

4.

  1. while (matcher.find()) {  

尝试在目标字符串里查找下一个匹配子串。即进行遍历筛选,如果找到匹配子串,则会返回true;

5.

  1. String faceText = matcher.group()  
返回当前查找而获得的与组匹配的子串内容。即取得筛选出的表情代码。

6.

  1. key = key.substring(key.indexOf("[")+1, key.indexOf("]"));  

取得"["和"]"内表情代码对应的资源命名,之后就通过该资源名在drawable文件夹中找到对应的图片资源,解析为Bitmap对象:

  1. BitmapFactory.Options options = new BitmapFactory.Options();  
  2.                 Bitmap bitmap = BitmapFactory.decodeResource(getContext().getResources(),  
  3.                         getContext().getResources().getIdentifier(key, "drawable", getContext().getPackageName()), options);  

7.

  1. ImageSpan imageSpan = new ImageSpan(getContext(), bitmap);  
  2. int startIndex = text.indexOf(faceText, start);  
  3.                 int endIndex = startIndex + faceText.length();  

传入Bitmap参数,构建ImageSpan对象。然后取得该表情代码在完整字符串中的起始索引和结束索引,即计算该表情的插入位置。

之后即可调用setSpan()方法将文本中的表情代码替换为表情图片了。

8.

  1. spannableString.setSpan(imageSpan, startIndex, endIndex, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);     

这里的第四个参数flag用于控制行为,取值包括如下:

Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括,即在指定范围的前面和后面再插入新字符都不会应用该样式 
Spannable.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括,后面包括。即仅在范围字符的后面再插入新字符时才会应用该样式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE:前面包括,后面不包括。
Spannable.SPAN_INCLUSIVE_INCLUSIVE:前后都包括。

源码

http://download.csdn.NET/detail/alfred_c/9140067

参考

http://blog.csdn.net/harvic880925/article/details/38984705

http://www.bmob.cn

原创粉丝点击