TextView算是android開發中最最常用的控件了,有的時候,我們要給一個TextView中的顯示的文字設定不同的樣式或者響應事件,比如同一個TextView中,有的字是紅色,有的字是藍色,有的字點選之後有響應事件,有的點選之後沒有響應事件,甚至我們想在TextView中顯示一個數學公式等等,那麼對于形形色色的需求我們有沒有解決方案呢?當然有,一種是使用HTML來解決,另一種就是使用SpannableString,HTML比較簡單,本文主要介紹後者。SpannableString可以用來顯示複合文本,我們可以通過SpannableString給文本設定各種各樣的樣式,下面我們就來看看SpannableString的一些常見用法。
1.設定TextView的背景顔色
給TextView設定背景顔色這本身是很簡單的,在XML檔案中直接加入background屬性即可,下面我們來看看怎麼樣通過SpannableString來給TextView設定背景顔色:
tv1 = (TextView) this.findViewById(R.id.tv1);
SpannableString ss1 = new SpannableString("設定背景顔色");
ss1.setSpan(new BackgroundColorSpan(Color.parseColor("#FFD700")), 0,
ss1.length(), Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
tv1.setText(ss1);
首先拿到一個TextView,然後構造一個 SpannableString,構造方法中傳入的參數就是我們要顯示的文字,然後就是一個最終要的方法,通過setSpan來設定背景色,第一個參數是我們要設定的背景顔色,第二第三個參數是我們要給哪一段的文字設定背景(該段文字的startIndex和endIndex),最後一個參數有四個值:
/**
* Non-0-length spans of type SPAN_INCLUSIVE_EXCLUSIVE expand
* to include text inserted at their starting point but not at their
* ending point. When 0-length, they behave like marks.
*/
public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;
/**
* Spans of type SPAN_INCLUSIVE_INCLUSIVE expand
* to include text inserted at either their starting or ending point.
*/
public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;
/**
* Spans of type SPAN_EXCLUSIVE_EXCLUSIVE do not expand
* to include text inserted at either their starting or ending point.
* They can never have a length of 0 and are automatically removed
* from the buffer if all the text they cover is removed.
*/
public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;
/**
* Non-0-length spans of type SPAN_EXCLUSIVE_INCLUSIVE expand
* to include text inserted at their ending point but not at their
* starting point. When 0-length, they behave like points.
*/
public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;
這四個值分别表示 1.前面包括,後面不包括,即在文本前插入新的文本會應用該樣式,而在文本後插入新文本不會應用該樣式 2.前面包括,後面包括,即在文本前插入新的文本會應用該樣式,而在文本後插入新文本也會應用該樣式 3.前面不包括,後面不包括 4.前面不包括,後面包括 好了,我們這裡設定的是前面不包括,後面包括,我們看看效果:
![](https://img.laitimes.com/img/_0nNw4CM6IyYiwiM6ICdiwiIyVGduV2QvwVe0lmdhJ3ZvwFM38CXlZHbvN3cpR2Lc1TPB10QGtWUCpEMJ9CXsxWam9CXwADNvwVZ6l2c052bm9CXUJDT1wkNhVzLcRnbvZ2LcZXUYpVd1kmYr50MZV3YyI2cKJDT29GRjBjUIF2LcRHelR3LcJzLctmch1mclRXY39jMxEjMxQDNzIzNxETM1EDMy8CX0Vmbu4GZzNmLn9Gbi1yZtl2Lc9CX6MHc0RHaiojIsJye.jpg)
當我們點選按鈕的時候會不斷往tv1中追加新的文本,這時新的文本會自動使用這個背景樣式,這是因為我們的最後一個參數設定為了Spanned.SPAN_EXCLUSIVE_INCLUSIVE,我們的點選事件是這樣的:
tv1.append("1234");
2.給文本設定點選事件
文本設定點選事件本身也是非常簡單,之間在XML檔案中設定clickable屬性為true,然後就可以像給Button設定點選事件一樣給TextView設定點選事件了,但是如果我們隻想給一個TextView中的某幾個文字設定點選事件,而不想給整個TextView設定點選事件,那麼該怎麼做?看下面的代碼:
tv2 = (TextView) this.findViewById(R.id.tv2);
SpannableString ss2 = new SpannableString("點我吧123456");
ss2.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Log.i("lenve", "tv2---onClick");
Toast.makeText(MainActivity.this, "點我呀", Toast.LENGTH_SHORT)
.show();
}
}, 0, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv2.setText(ss2);
// 設定tv2為可點選狀态
tv2.setMovementMethod(LinkMovementMethod.getInstance());
大部分和1中的代碼一樣,我們主要來說說setSpan方法,第一個參數是一個ClickableSpan對象,這裡有一個onClick方法,該方法中就是我們對點選事件的響應,後面幾個參數和前文一樣,我們來看看效果:
同一個TextView中,隻有前三個文字會響應點選事件,其餘文字都不會響應該事件。這裡要特别注意最後一行代碼,我們要設定該TextView為可點選狀态。
3.設定文本顔色
在1中我們設定了TextView的背景顔色,這裡我們看看怎麼設定文本的顔色:
tv3 = (TextView) this.findViewById(R.id.tv3);
SpannableString ss3 = new SpannableString("設定文本顔色");
ss3.setSpan(new ForegroundColorSpan(Color.parseColor("#FF3030")), 0,
ss3.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv3.setText(ss3);
setSpan函數第一個參數是我們要設定的文本顔色,後面幾個參數含義和之前介紹的一樣,我們看看效果:
4.設定删除線效果
删除線效果在一些電商App中會用到,不要1999(一個删除線),不要998(一個删除線),隻要XXX,我們看看怎麼實作:
tv6 = (TextView) this.findViewById(R.id.tv6);
SpannableString ss6 = new SpannableString("删除線");
ss6.setSpan(new StrikethroughSpan(), 0, ss6.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv6.setText(ss6);
setSpan方法的第一個參數傳入new StrikethroughSpan()即可,看看效果:
5.設定下劃線效果
tv7 = (TextView) this.findViewById(R.id.tv7);
SpannableString ss7 = new SpannableString("下劃線");
ss7.setSpan(new UnderlineSpan(), 0, ss7.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv7.setText(ss7);
setSpan方法第一個參數傳入new UnderlineSpan()即可。
6.在TextView中設定圖檔
經常有人會問能不能在TextView中設定圖檔,如果能,要怎麼設定,其實用SpannableString這個效果很容易實作,我們看看代碼:
tv8 = (TextView) this.findViewById(R.id.tv8);
SpannableString ss8 = new SpannableString("設定圖檔");
ss8.setSpan(
// DynamicDrawableSpan.ALIGN_BASELINE表示依照基線對齊
// DynamicDrawableSpan.ALIGN_BOTTOM表示依照底部對齊
new DynamicDrawableSpan(DynamicDrawableSpan.ALIGN_BOTTOM) {
@Override
public Drawable getDrawable() {
Drawable d = getResources().getDrawable(
R.drawable.ic_launcher);
d.setBounds(0, 0, 150, 150);
return d;
}
}, 0, 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);// 這裡的參數0,1表示将“設”字替換為圖檔
tv8.setText(ss8);
setSpan方法的第一個參數傳入一個DynamicDrawableSpan對象,其中這個對象的構造函數是圖檔的對齊方式,一共有兩種,如注釋,實作該類的getDrawable方法,傳回一個Drawable對象即可,注意這裡的圖檔會替換掉文字(如果我們使用這種效果,很多情況下就是要讓圖檔替換掉文字,是以這并不算一個問題),看效果圖:
“設”字被圖檔替換掉了。
7.基于X軸的縮放
對于TextView中的文本我們也可以執行一些縮放操作,我們看看代碼:
tv9 = (TextView) this.findViewById(R.id.tv9);
SpannableString ss9 = new SpannableString("基于X軸縮放");
// ScaleXSpan中的參數大于1表示橫向擴大,小于1大于0表示縮小,等于1表示正常顯示
ss9.setSpan(new ScaleXSpan(2), 0, ss9.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv9.setText(ss9);
隻需要在setSpan方法中傳入一個ScaleXSpan對象即可,裡邊參數含義看注釋。 效果圖如下:
8.設定字型粗體樣式
看代碼:
tv10 = (TextView) this.findViewById(R.id.tv10);
SpannableString ss10 = new SpannableString("字型樣式,粗體、斜體等");
ss10.setSpan(new StyleSpan(Typeface.BOLD), 5, 7,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv10.setText(ss10);
效果圖:
9.上下标的使用
上下标的使用可以讓我們很好的表達一個數學公式,比如完全平方差公式,這次我們先來看看效果圖:
不錯吧,那麼我們再來看看代碼實作:
tv11 = (TextView) this.findViewById(R.id.tv11);
SpannableString ss11 = new SpannableString("(x1 + x2)2 = x12+x22+2x1x2");
// 設定下标
ss11.setSpan(new SubscriptSpan(), 2, 3,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 設定下标字型大小
ss11.setSpan(new AbsoluteSizeSpan(30), 2, 3,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SubscriptSpan(), 7, 8,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 7, 8,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SubscriptSpan(), 14, 15,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 14, 15,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SubscriptSpan(), 18, 19,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 18, 19,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SubscriptSpan(), 23, 24,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 23, 24,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SubscriptSpan(), 25, 26,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 25, 26,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 設定上标
ss11.setSpan(new SuperscriptSpan(), 9, 10,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 9, 10,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SuperscriptSpan(), 15, 16,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 15, 16,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new SuperscriptSpan(), 19, 20,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss11.setSpan(new AbsoluteSizeSpan(30), 19, 20,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv11.setText(ss11);
這裡代碼有點長,不過大部分都是重複的,重要的都有注釋,不贅述。
10.設定超連結
SpannableString也可以用來設定超連結,我們看看代碼:
tv13 = (TextView) this.findViewById(R.id.tv13);
SpannableString ss13 = new SpannableString("打電話,發短信,發郵件,打開網頁");
ss13.setSpan(new URLSpan("tel:13534884482"), 0, 3,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss13.setSpan(new URLSpan("smsto:13534884482"), 4, 7,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss13.setSpan(new URLSpan("mailto:[email protected]"), 8, 11,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ss13.setSpan(new URLSpan("http://www.baidu.com"), 12, 16,
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
tv13.setText(ss13);
tv13.setMovementMethod(LinkMovementMethod.getInstance());
使用不同的協定可以分别跳轉到打電話頁面,發短信頁面,發郵件頁面以及打開網頁,我們看看效果圖:
好了,關于SpannableString的使用,這裡隻是給大家提供一個思路,更多的效果還要大家自己去探索,今晚就到這裡吧。
Demo下載下傳https://github.com/lenve/spannableStringTest