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 文本超鏈接


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