一、接口定義 1.Spanned 這是一個針對文本的接口,用來标記在文本的某些範圍之類,附屬了哪些對象。 public interface Spanned extends CharSequence 該接口是繼承了CharSequence,是以在android平台可以直接當做CharSequence來使用, 并且增加了很多特殊的文本處理功能。 該接口定義了很多Flag變量,注意以下幾個常用的flag标記,用來标記範圍
SPAN_INCLUSIVE_EXCLUSIVE SPAN_INCLUSIVE_INCLUSIVE SPAN_EXCLUSIVE_EXCLUSIVE SPAN_EXCLUSIVE_INCLUSIVE
主要的幾個接口,都是用來擷取标記範圍參數的: public int getSpanStart(Object tag); public int getSpanEnd(Object tag); public int getSpanFlags(Object tag); public <T> T[] getSpans(int start, int end, Class<T> type);
2.Spannable public interface Spannable extends Spanned
該接口繼承自Spanned,包含2個接口方法,和一個工廠類
public void setSpan(Object what, int start, int end, int flags); public void removeSpan(Object what);
該接口定義了一個工廠類,首先想到的是減少與實作類的耦合,提高可維護性。 你可以定義自己的工廠類,來實作不同的目的。裡面很巧妙的運用了一個靜态内部類, 既實作了Lazy Loading的單例模式,又巧妙解決了多線程安全的問題。這裡可以借鑒, 靜态内部類實作的單例模式。 public static class Factory { private static Spannable.Factory sInstance = new Spannable.Factory(); public static Spannabe.Factory getInstance() { return sInstance; } public Spannable newSpannable(CharSequence source) { return new SpannableString(source); } }
3.Editable public interface Editable extends Spannable, Appendable, CharSequence, GetChars 可以看到該接口主要繼承了Spannable,Appendable這2個接口,是以Editable既具有Spannable的功能,又能改變text的内容。 主要的幾個接口為: public Editable replace(int st, int en, CharSequence source, int start, int end); public Editable replace(int st, int en, CharSequence text); //replace(st, en, text, 0, text.length()); public Editable insert(int where, CharSequence text, int start, int end); public Editable delete(int st, int en); //replace(st, en, "", 0, 0); public Editable append(CharSequence text); //replace(length(), length(), text, 0, text.length()); //對輸入的内容可進行過濾限制 public void setFilters(InputFilter[] filters); public InputFilter[] getFilters();
同樣的該接口也定義了一個工廠類,與Spannable類似。 …… ……
public Editable newEditable(CharSequence source) { return new SpannableStringBuilder(source); } …… …...
二、TextView.BufferType
TextView控件設定文本時,有個參數叫TextView.BufferType,這是個枚舉類,共有3個枚舉值
public enum BufferTpe { NORMAL, SPANNABLE, EDITABLE }
在TextView中,預設的bufferType為BufferType.NORMAL,即預設的bufferType既不是Spannable,也不是Editable: private BufferType mBufferType = BufferType. NORMAL ;
有2個工廠對象,都是系統預設值:
private Editable.Factory mEditableFactory = Editable.Factory.getInstance();
private Spannable.Factory mSpannableFactory = Spannable.Factory.getInstance();
在TextView中的setText()方法: setText(CharSequence text, BufferType type); setText(CharSequence text); //如果不設定bufferType,會采用預設的bufferType,即BufferType.NORMAL 其中關于BufferType的主要代碼: if (type == BufferType.EDITABLE || getKeyListener() != null || needEditableForNotification) { createEditorIfNeeded(); Editable t = mEditableFactory.newEditable(text); text = t; setFilters(t, mFilters); InputMethodManager imm = InputMethodManager.peekInstance(); if (imm != null) imm.restartInput(this); } else if (type == BufferType.SPANNABLE || mMovement != null) { text = mSpannableFactory.newSpannable(text); } else if (!(text instanceof CharWrapper)) { text = TextUtils.stringOrSpannedString(text); } 可以看出根據不同的BufferType,用類工廠的模式建立出不同的text,預設情況下,類工廠都是系統預設定義好的,如:mEditableFactory、mSpannableFactory。 TextView中提供了更換Factory的可能,使得開發者能夠根據需求自定義: public final void setEditableFactory(Editable.Factory factory) { mEditableFactory = factory; setText(mText); } public final void setSpannableFactory(Spannable.Factory factory) { mSpannableFactory = factory; setText(mText); }
在EditText中,setText()時, 預設已經把bufferType設定為Editable了: public void setText(CharSequence text, BufferType type) { super.setText(text, BuffetType.EDITABLE); } 是以,EditText的getText(),得到的也是Editable類型: public Editable getText() { return (Editable)super.getText(); }
三、代碼執行個體
1.利用Spannable設定各種效果 Spannable span = Spannable.Factory.getInstance().newSpannable("Click here to see more."); span.setSpan(new UnderlineSpan(), 0, 5, Spanned.SPAN_INCLUSIVE_INCLUSIVE); tv.setText(span); 出現的效果:在"Click"下面會出現下劃線, Click here to see more. 主要方法:setSpan(Object what, int start, int end, int flags); start:起始位置, inclusive end:結束位置, exclusive,最終起效果的字元長度為 end-start flags: 其主要含義為辨別在Span範圍内的文本前後輸入新的字元時,是否把它們也應用于這個效果。
SPAN_INCLUSIVE_INCLUSIVE效果: Click here to see more. //原始應用效果,在Click下面會有下劃線 aClick here to see more. //在Click之前輸入一個字元a,則a也會有下劃線 aClicka here to see more. //在Click之後輸入一個字元a,a也有下劃線
SPAN_INCLUSIVE_EXCLUSIVE: Click here to see more.
aClick here to see more.
aClicka here to see more. //在Click之後輸入一個字元a,a并沒有下劃線 2.利用TextView的BufferType設定文本内容, TextView tv = ….; tv.setText("Text", BufferType.EDITABLE); Editable editable = (Editable) tv.getText(); editable.append(" append test."); 在UI上的顯示依次為: Text Text append test. 注意在setText()時,一定要把BufferType設定為BufferType.EDITABLE,否則getText()得到不是Editable類型對象。
四、總結
1.Spannable可以在給定的字元區域内使用各種樣式; 2.Editable繼承自Spannable,同樣也可以在給定的字元區域内使用各種樣式; 3.Editable類似于StringBuffer可以增加、删除、修改字元,也就是getText()後可調用append方法設定修改文本内容; 4.TextView的setText(),預設的BufferType為BufferType.NORMAL; 5.EditText的setText(),已經将BuffetType寫死為BufferType.EDITABLE; 6.TextView的getText()傳回類型為CharSequence; 7.EditText的getText()傳回類型為Editable;