一、接口定义
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;