一淳玩、概述
1劲藐、SpannableString牵辣、SpannableStringBuilder與String的關系
首先SpannableString、SpannableStringBuilder基本上與String差不多跛璧,也是用來存儲字符串,但它們倆的特殊就在于有一個SetSpan()函數新啼,能給這些存儲的String添加各種格式或者稱樣式(Span)追城,將原來的String以不同的樣式顯示出來,比如在原來String上加下劃線燥撞、加背景色漓柑、改變字體顏色、用圖片把指定的文字給替換掉,等等辆布。所以瞬矩,總而言之,SpannableString锋玲、SpannableStringBuilder與String一樣景用,?首先也是傳字符串,但SpannableString惭蹂、SpannableStringBuilder可以對這些字符串添加額外的樣式信息伞插,但String則不行。
注意:如果這些額外信息能被所用的方式支持盾碗,比如將SpannableString傳給TextView媚污;也有對這些額外信息不支持的,比如前一章講到的Canvas繪制文字廷雅,對于不支持的情況耗美,SpannableString和SpannableStringBuilder就是退化為String類型,直接顯示原來的String字符串航缀,而不會再顯示這些附加的額外信息商架。
2、SpannableString與SpannableStringBuilder區(qū)別
它們的區(qū)別在于 SpannableString像一個String一樣芥玉,構造對象的時候傳入一個String蛇摸,之后再無法更改String的內容,也無法拼接多個 SpannableString灿巧;而SpannableStringBuilder則更像是StringBuilder赶袄,它可以通過其append()方法來拼接多個String:
[java]view plaincopy
//使用SpannableString,必須一次傳入抠藕,構造完成
SpannableString?word?=newSpannableString("歡迎光臨Harvic的博客");
//使用SpannableStringBuilder,可以使用append()再添加
SpannableStringBuilder?multiWord?=newSpannableStringBuilder();
multiWord.append("歡迎光臨");
multiWord.append("Harvic的");
multiWord.append("博客");
(轉自博客:《android - SpannableString或SpannableStringBuilder以及string.xml文件中的整型和string型代替》)
因為Spannable等最終都實現了CharSequence接口弃鸦,所以可以直接把SpannableString和SpannableStringBuilder通過TextView.setText()設置給TextView。
void setSpan (Object what, int start, int end, int flags)
函數意義:給SpannableString或SpannableStringBuilder特定范圍的字符串設定Span樣式唬格,可以設置多個(比如同時加上下劃線和刪除線等),Falg參數標識了當在所標記范圍前和標記范圍后緊貼著插入新字符時的動作颜说,即是否對新插入的字符應用同樣的樣式购岗。(這個后面會具體舉例說明)
參數說明:
object what :對應的各種Span,后面會提到门粪;
int start:開始應用指定Span的位置喊积,索引從0開始
int end:結束應用指定Span的位置,特效并不包括這個位置玄妈。比如如果這里數為3(即第4個字符)乾吻,第4個字符不會有任何特效髓梅。從下面的例子也可以看出來。
int flags:取值有如下四個
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括绎签,即在指定范圍的前面和后面插入新字符都不會應用新樣式Spannable.SPAN_EXCLUSIVE_INCLUSIVE:前面不包括枯饿,后面包括。即僅在范圍字符的后面插入新字符時會應用新樣式
Spannable.SPAN_INCLUSIVE_EXCLUSIVE:前面包括诡必,后面不包括奢方。
Spannable.SPAN_INCLUSIVE_INCLUSIVE:前后都包括。
舉個例子來說明這個前后包括的問題:
由于Flag的作用是用來指定范圍前后輸入新的字符時爸舒,會不會應用效果的蟋字,所以我們利用EditText來顯示SpannableString
(1)、布局XML中加入一個EditText控件:
[html]view plaincopy
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="com.example.try_spannable_blog.MainActivity">
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content"/>
(2)扭勉、這里用一個改變字體顏色的Span來做下演示
[java]view plaincopy
publicclassMainActivityextendsActivity?{
privateEditText?editText;
@Override
protectedvoidonCreate(Bundle?savedInstanceState)?{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText?=?(EditText)findViewById(R.id.edit);
//改變字體顏色
//先構造SpannableString
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
//再構造一個改變字體顏色的Span
ForegroundColorSpan?span?=newForegroundColorSpan(Color.BLUE);
//將這個Span應用于指定范圍的字體
spanString.setSpan(span,1,3,?Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//設置給EditText顯示出來
editText.setText(spanString);
}
}
初始化效果是這樣的:
分別在設置Span的前面和后面加入新文字鹊奖,結果是這樣的
在前面和后面都加入蝦米兩個字,可見涂炎,前面的蝦米沒有任何效果忠聚,后面的則不同,添加上相同的Span特效璧尸,這是由于我們設置了Spannable.SPAN_EXCLUSIVE_INCLUSIVE的原因咒林,即(前面不應用特效熬拒,后面應用特效)爷光,其它幾個Flags參數的含義想必大家也都清楚了。在此就不再贅述澎粟。
在前面的一個小示例,大家應該也可以看出活烙,要應用一個Span總共分三步:
1徐裸、構造String
2、構造Span
3啸盏、利用SetSpan()對指定范圍的String應用這個Span
1重贺、字體顏色設置(ForegroundColorSpan)
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
//再構造一個改變字體顏色的Span
ForegroundColorSpan?span?=newForegroundColorSpan(Color.BLUE);
//將這個Span應用于指定范圍的字體
spanString.setSpan(span,1,5,?Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//設置給EditText顯示出來
editText.setText(spanString);
效果:
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
BackgroundColorSpan?span?=newBackgroundColorSpan(Color.YELLOW);
spanString.setSpan(span,0,3,?Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
AbsoluteSizeSpan?span?=newAbsoluteSizeSpan(16);
spanString.setSpan(span,2,5,?Spannable.SPAN_INCLUSIVE_INCLUSIVE);
editText.setText(spanString);
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
StyleSpan?span?=newStyleSpan(Typeface.BOLD_ITALIC);
spanString.setSpan(span,1,4,?Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
StrikethroughSpan?span?=newStrikethroughSpan();
spanString.setSpan(span,2,5,?Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
UnderlineSpan?span?=newUnderlineSpan();
spanString.setSpan(span,1,4,?Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
ImagSpan有很多構造函數谭期,一般是通過傳入Drawableg來構造堵第,詳細的構造說明看這里:http://developer.android.com/reference/android/text/style/ImageSpan.html
[java]view plaincopy
SpannableString?spanString?=newSpannableString("歡迎光臨Harvic的博客");
Drawable?d?=?getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0,0,?d.getIntrinsicWidth(),?d.getIntrinsicHeight());
ImageSpan?span?=newImageSpan(d,?ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span,2,4,?Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
這個函數的不同之處在于,前幾都是在原來文字的基礎上加上特效隧出,而這里卻是利用圖片將文字替換踏志。如果遇到不支持顯示圖片的函數,比如前一篇中的canvas繪圖鸳劳。就會退化成String狰贯,即以原來的String字符串來顯示。