SpannableString使用详解

TextView算是Android开发中最最常用的控件了,有的时候,我们要给一个TextView中的显示的文字设置不同的样式或者响应事件,比如同一个TextView中,有的字是红色,有的字是蓝色,有的字点击之后有响应事件,有的点击之后没有响应事件,甚至我们想在TextView中显示一个数学公式等等,那么对于形形色色的需求我们有没有解决方案呢?当然有,一种是使用HTML来解决,另一种就是使用SpannableString,HTML比较简单,本文主要介绍后者。SpannableString可以用来显示复合文本,我们可以通过SpannableString给文本设置各种各样的样式,下面我们就来看看SpannableString的一些常见用法。

1.设置TextView的背景颜色

给TextView设置背景颜色这本身是很简单的,在XML文件中直接加入background属性即可,下面我们来看看怎么样通过SpannableString来给TextView设置背景颜色:
[java] view plain copy
 print?
  1. tv1 = (TextView) this.findViewById(R.id.tv1);  
  2.         SpannableString ss1 = new SpannableString("设置背景颜色");  
  3.         ss1.setSpan(new BackgroundColorSpan(Color.parseColor("#FFD700")), 0,  
  4.                 ss1.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);  
  5.         tv1.setText(ss1);  

首先拿到一个TextView,然后构造一个SpannableString,构造方法中传入的参数就是我们要显示的文字,然后就是一个最终要的方法,通过setSpan来设置背景色,第一个参数是我们要设置的背景颜色,第二第三个参数是我们要给哪一段的文字设置背景(该段文字的startIndex和endIndex),最后一个参数有四个值:

[java] view plain copy
 print?
  1. /** 
  2.  * Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand 
  3.  * to include text inserted at their starting point but not at their 
  4.  * ending point.  When 0-length, they behave like marks. 
  5.  */  
  6. public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;  
  7.   
  8. /** 
  9.  * Spans of type SPAN_INCLUSIVE_INCLUSIVE expand 
  10.  * to include text inserted at either their starting or ending point. 
  11.  */  
  12. public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;  
  13.   
  14. /** 
  15.  * Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand 
  16.  * to include text inserted at either their starting or ending point. 
  17.  * They can never have a length of 0 and are automatically removed 
  18.  * from the buffer if all the text they cover is removed. 
  19.  */  
  20. public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;  
  21.   
  22. /** 
  23.  * Non-0-length spans of type SPAN_EXCLUSIVE_INCLUSIVE expand 
  24.  * to include text inserted at their ending point but not at their 
  25.  * starting point.  When 0-length, they behave like points. 
  26.  */  
  27. public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;  

这四个值分别表示
1.前面包括,后面不包括,即在文本前插入新的文本会应用该样式,而在文本后插入新文本不会应用该样式
2.前面包括,后面包括,即在文本前插入新的文本会应用该样式,而在文本后插入新文本也会应用该样式
3.前面不包括,后面不包括
4.前面不包括,后面包括
好了,我们这里设置的是前面不包括,后面包括,我们看看效果:


当我们点击按钮的时候会不断往tv1中追加新的文本,这时新的文本会自动使用这个背景样式,这是因为我们的最后一个参数设置为了Spanned.SPAN_EXCLUSIVE_INCLUSIVE,我们的点击事件是这样的:
[java] view plain copy
 print?
  1. tv1.append("1234");  

2.给文本设置点击事件

文本设置点击事件本身也是非常简单,之间在XML文件中设置clickable属性为true,然后就可以像给Button设置点击事件一样给TextView设置点击事件了,但是如果我们只想给一个TextView中的某几个文字设置点击事件,而不想给整个TextView设置点击事件,那么该怎么做?看下面的代码:
[java] view plain copy
 print?
  1. tv2 = (TextView) this.findViewById(R.id.tv2);  
  2. SpannableString ss2 = new SpannableString("点我吧123456");  
  3. ss2.setSpan(new ClickableSpan() {  
  4.   
  5.     @Override  
  6.     public void onClick(View widget) {  
  7.         Log.i("lenve""tv2---onClick");  
  8.         Toast.makeText(MainActivity.this"点我呀", Toast.LENGTH_SHORT)  
  9.                 .show();  
  10.     }  
  11. }, 03, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  12. tv2.setText(ss2);  
  13. // 设置tv2为可点击状态  
  14. tv2.setMovementMethod(LinkMovementMethod.getInstance());  

大部分和1中的代码一样,我们主要来说说setSpan方法,第一个参数是一个ClickableSpan对象,这里有一个onClick方法,该方法中就是我们对点击事件的响应,后面几个参数和前文一样,我们来看看效果:


同一个TextView中,只有前三个文字会响应点击事件,其余文字都不会响应该事件。这里要特别注意最后一行代码,我们要设置该TextView为可点击状态。

3.设置文本颜色

在1中我们设置了TextView的背景颜色,这里我们看看怎么设置文本的颜色:
[java] view plain copy
 print?
  1. tv3 = (TextView) this.findViewById(R.id.tv3);  
  2.         SpannableString ss3 = new SpannableString("设置文本颜色");  
  3.         ss3.setSpan(new ForegroundColorSpan(Color.parseColor("#FF3030")), 0,  
  4.                 ss3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         tv3.setText(ss3);  

setSpan函数第一个参数是我们要设置的文本颜色,后面几个参数含义和之前介绍的一样,我们看看效果:


4.设置删除线效果

删除线效果在一些电商App中会用到,不要1999(一个删除线),不要998(一个删除线),只要XXX,我们看看怎么实现:
[java] view plain copy
 print?
  1. tv6 = (TextView) this.findViewById(R.id.tv6);  
  2.         SpannableString ss6 = new SpannableString("删除线");  
  3.         ss6.setSpan(new StrikethroughSpan(), 0, ss6.length(),  
  4.                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         tv6.setText(ss6);  

setSpan方法的第一个参数传入new StrikethroughSpan()即可,看看效果:



5.设置下划线效果

[java] view plain copy
 print?
  1. tv7 = (TextView) this.findViewById(R.id.tv7);  
  2.         SpannableString ss7 = new SpannableString("下划线");  
  3.         ss7.setSpan(new UnderlineSpan(), 0, ss7.length(),  
  4.                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         tv7.setText(ss7);  

setSpan方法第一个参数传入new UnderlineSpan()即可。

6.在TextView中设置图片

经常有人会问能不能在TextView中设置图片,如果能,要怎么设置,其实用SpannableString这个效果很容易实现,我们看看代码:
[java] view plain copy
 print?
  1. tv8 = (TextView) this.findViewById(R.id.tv8);  
  2. SpannableString ss8 = new SpannableString("设置图片");  
  3. ss8.setSpan(  
  4. // DynamicDrawableSpan.ALIGN_BASELINE表示依照基线对齐  
  5. // DynamicDrawableSpan.ALIGN_BOTTOM表示依照底部对齐  
  6.         new DynamicDrawableSpan(DynamicDrawableSpan.ALIGN_BOTTOM) {  
  7.   
  8.             @Override  
  9.             public Drawable getDrawable() {  
  10.                 Drawable d = getResources().getDrawable(  
  11.                         R.drawable.ic_launcher);  
  12.                 d.setBounds(00150150);  
  13.                 return d;  
  14.             }  
  15.         }, 01, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);// 这里的参数0,1表示将“设”字替换为图片  
  16. tv8.setText(ss8);  

setSpan方法的第一个参数传入一个DynamicDrawableSpan对象,其中这个对象的构造函数是图片的对齐方式,一共有两种,如注释,实现该类的getDrawable方法,返回一个Drawable对象即可,注意这里的图片会替换掉文字(如果我们使用这种效果,很多情况下就是要让图片替换掉文字,所以这并不算一个问题),看效果图:


“设”字被图片替换掉了。

7.基于X轴的缩放

对于TextView中的文本我们也可以执行一些缩放操作,我们看看代码:
[java] view plain copy
 print?
  1. tv9 = (TextView) this.findViewById(R.id.tv9);  
  2. SpannableString ss9 = new SpannableString("基于X轴缩放");  
  3. // ScaleXSpan中的参数大于1表示横向扩大,小于1大于0表示缩小,等于1表示正常显示  
  4. ss9.setSpan(new ScaleXSpan(2), 0, ss9.length(),  
  5.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  6. tv9.setText(ss9);  
只需要在setSpan方法中传入一个ScaleXSpan对象即可,里边参数含义看注释。
效果图如下:



8.设置字体粗体样式

看代码:
[java] view plain copy
 print?
  1. tv10 = (TextView) this.findViewById(R.id.tv10);  
  2.         SpannableString ss10 = new SpannableString("字体样式,粗体、斜体等");  
  3.         ss10.setSpan(new StyleSpan(Typeface.BOLD), 57,  
  4.                 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5.         tv10.setText(ss10);  

效果图:



9.上下标的使用

上下标的使用可以让我们很好的表达一个数学公式,比如完全平方差公式,这次我们先来看看效果图:



不错吧,那么我们再来看看代码实现:
[java] view plain copy
 print?
  1. tv11 = (TextView) this.findViewById(R.id.tv11);  
  2. SpannableString ss11 = new SpannableString("(x1 + x2)2 = x12+x22+2x1x2");  
  3. // 设置下标  
  4. ss11.setSpan(new SubscriptSpan(), 23,  
  5.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  6. // 设置下标字体大小  
  7. ss11.setSpan(new AbsoluteSizeSpan(30), 23,  
  8.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  9. ss11.setSpan(new SubscriptSpan(), 78,  
  10.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  11. ss11.setSpan(new AbsoluteSizeSpan(30), 78,  
  12.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  13. ss11.setSpan(new SubscriptSpan(), 1415,  
  14.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  15. ss11.setSpan(new AbsoluteSizeSpan(30), 1415,  
  16.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  17. ss11.setSpan(new SubscriptSpan(), 1819,  
  18.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  19. ss11.setSpan(new AbsoluteSizeSpan(30), 1819,  
  20.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  21. ss11.setSpan(new SubscriptSpan(), 2324,  
  22.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  23. ss11.setSpan(new AbsoluteSizeSpan(30), 2324,  
  24.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  25. ss11.setSpan(new SubscriptSpan(), 2526,  
  26.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  27. ss11.setSpan(new AbsoluteSizeSpan(30), 2526,  
  28.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  29. // 设置上标  
  30. ss11.setSpan(new SuperscriptSpan(), 910,  
  31.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  32. ss11.setSpan(new AbsoluteSizeSpan(30), 910,  
  33.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  34. ss11.setSpan(new SuperscriptSpan(), 1516,  
  35.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  36. ss11.setSpan(new AbsoluteSizeSpan(30), 1516,  
  37.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  38. ss11.setSpan(new SuperscriptSpan(), 1920,  
  39.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  40. ss11.setSpan(new AbsoluteSizeSpan(30), 1920,  
  41.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  42. tv11.setText(ss11);  

这里代码有点长,不过大部分都是重复的,重要的都有注释,不赘述。


10.设置超链接

SpannableString也可以用来设置超链接,我们看看代码:
[java] view plain copy
 print?
  1. tv13 = (TextView) this.findViewById(R.id.tv13);  
  2. SpannableString ss13 = new SpannableString("打电话,发短信,发邮件,打开网页");  
  3. ss13.setSpan(new URLSpan("tel:13534884482"), 03,  
  4.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  5. ss13.setSpan(new URLSpan("smsto:13534884482"), 47,  
  6.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  7. ss13.setSpan(new URLSpan("mailto:[email protected]"), 811,  
  8.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  9. ss13.setSpan(new URLSpan("http://www.baidu.com"), 1216,  
  10.         Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
  11. tv13.setText(ss13);  
  12. tv13.setMovementMethod(LinkMovementMethod.getInstance());  


SpannableString 常用API:

Android系统通过SpannableString类来对指定文本进行相关处理,具体有以下功能:

1、BackgroundColorSpan 背景色 
2、ClickableSpan 文本可点击,有点击事件
3、ForegroundColorSpan 文本颜色(前景色)
4、MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
5、MetricAffectingSpan 父类,一般不用
6、RasterizerSpan 光栅效果
7、StrikethroughSpan 删除线(中划线)
8、SuggestionSpan 相当于占位符
9、UnderlineSpan 下划线
10、AbsoluteSizeSpan 绝对大小(文本字体)
11、DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
12、ImageSpan 图片
13、RelativeSizeSpan 相对大小(文本字体)
14、ReplacementSpan 父类,一般不用
15、ScaleXSpan 基于x轴缩放
16、StyleSpan 字体样式:粗体、斜体等
17、SubscriptSpan 下标(数学公式会用到)
18、SuperscriptSpan 上标(数学公式会用到)
19、TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
20、TypefaceSpan 文本字体
21、URLSpan 文本超链接


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章