首先SpannableString、SpannableStringBuilder基本上與String差很少,也是用來存儲字符串,但它們倆的特殊就在於有一個SetSpan()函數,能給這些存儲的String添加各類格式或者稱樣式(Span),將原來的String以不一樣的樣式顯示出來,好比在原來String上加下劃線、加背景色、改變字體顏色、用圖片把指定的文字給替換掉,等等。因此,總而言之,SpannableString、SpannableStringBuilder與String同樣, 首先也是傳字符串,但SpannableString、SpannableStringBuilder能夠對這些字符串添加額外的樣式信息,但String則不行。html
注意:若是這些額外信息能被所用的方式支持,好比將SpannableString傳給TextView;也有對這些額外信息不支持的,好比前一章講到的Canvas繪製文字,對於不支持的狀況,SpannableString和SpannableStringBuilder就是退化爲String類型,直接顯示原來的String字符串,而不會再顯示這些附加的額外信息。java
它們的區別在於 SpannableString像一個String同樣,構造對象的時候傳入一個String,以後再沒法更改String的內容,也沒法拼接多個 SpannableString;而SpannableStringBuilder則更像是StringBuilder,它能夠經過其append()方法來拼接多個String:
android
[java] view plaincopycanvas
//使用SpannableString,必須一次傳入,構造完成 app
SpannableString word = new SpannableString("歡迎光臨Harvic的博客"); ide
//使用SpannableStringBuilder,可使用append()再添加 函數
SpannableStringBuilder multiWord = new SpannableStringBuilder(); 佈局
multiWord.append("歡迎光臨"); 字體
multiWord.append("Harvic的"); ui
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
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
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" >
<EditText
android:id="@+id/edit"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RelativeLayout>
(2)、這裏用一個改變字體顏色的Span來作下演示
[java] view plaincopy
public class MainActivity extends Activity {
private EditText editText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
editText = (EditText)findViewById(R.id.edit);
//改變字體顏色
//先構造SpannableString
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
//再構造一個改變字體顏色的Span
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
//將這個Span應用於指定範圍的字體
spanString.setSpan(span, 1, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//設置給EditText顯示出來
editText.setText(spanString);
}
}
初始化效果是這樣的:
分別在設置Span的前面和後面加入新文字,結果是這樣的
在前面和後面都加入蝦米兩個字,可見,前面的蝦米沒有任何效果,後面的則不一樣,添加上相同的Span特效,這是因爲咱們設置了Spannable.SPAN_EXCLUSIVE_INCLUSIVE的緣由,即(前面不該用特效,後面應用特效),其它幾個Flags參數的含義想必你們也都清楚了。在此就再也不贅述。
在前面的一個小示例,你們應該也能夠看出,要應用一個Span總共分三步:
一、構造String
二、構造Span
三、利用SetSpan()對指定範圍的String應用這個Span
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
//再構造一個改變字體顏色的Span
ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);
//將這個Span應用於指定範圍的字體
spanString.setSpan(span, 1, 5, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);
//設置給EditText顯示出來
editText.setText(spanString);
效果:
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
BackgroundColorSpan span = new BackgroundColorSpan(Color.YELLOW);
spanString.setSpan(span, 0, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
AbsoluteSizeSpan span = new AbsoluteSizeSpan(16);
spanString.setSpan(span, 2, 5, Spannable.SPAN_INCLUSIVE_INCLUSIVE);
editText.setText(spanString);
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
StyleSpan span = new StyleSpan(Typeface.BOLD_ITALIC);
spanString.setSpan(span, 1, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
StrikethroughSpan span = new StrikethroughSpan();
spanString.setSpan(span, 2, 5, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
[java] view plaincopy
SpannableString spanString = new SpannableString("歡迎光臨Harvic的博客");
UnderlineSpan span = new UnderlineSpan();
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 = new SpannableString("歡迎光臨Harvic的博客");
Drawable d = getResources().getDrawable(R.drawable.ic_launcher);
d.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
ImageSpan span = new ImageSpan(d, ImageSpan.ALIGN_BASELINE);
spanString.setSpan(span, 2, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
editText.setText(spanString);
這個函數的不一樣之處在於,前幾都是在原來文字的基礎上加上特效,而這裏倒是利用圖片將文字替換。若是遇到不支持顯示圖片的函數,好比前一篇中的canvas繪圖。就會退化成String,即以原來的String字符串來顯示