SpannableString:
This is the class for text whose content is immutable but to which markup objects can be attached and detached.
SpannableString構(gòu)造的字符串后不可變了,標(biāo)記對(duì)象可以添加和刪除
SpannableStringBuilder:
This is the class for text whose content and markup can both be changed.
SpannableStringBuilder 構(gòu)造的內(nèi)容和標(biāo)記對(duì)象都可更改
//object what :對(duì)應(yīng)的各種Span
// int start:開(kāi)始應(yīng)用指定Span的位置,索引從0開(kāi)始
//int end:結(jié)束應(yīng)用指定Span的位置,不包含
//int flags 見(jiàn)Spanned中的描述
public void setSpan(Object what, int start, int end, int flags) {
setSpan(true, what, start, end, flags, true/*enforceParagraph*/);
}
Spanned
This is the interface for text that has markup objects ranges of it.
public interface Spanned
extends CharSequence
{
//在標(biāo)志位【start,end)后添加文字,新添加的文字不會(huì)有任何設(shè)置的屬性,前邊邊的添加的文字會(huì)帶有設(shè)置的what屬性
public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK;
//在標(biāo)志位【start,end)前后添加文字,新添加的文字會(huì)有設(shè)置的屬性
public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;
//在標(biāo)志位【start,end)前后添加文字,新添加的文字不會(huì)有任何設(shè)置的屬性
public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;
//在標(biāo)志位【start,end)前添加文字,新添加的文字不會(huì)有任何設(shè)置的屬性,后邊的添加的文字會(huì)帶有設(shè)置的what屬性
public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;
}
Spannable
靜態(tài)單例 實(shí)現(xiàn)工廠方法 返回的SpannableString,
This is the class for text whose content is immutable but to which markup objects can be attached and detached.
就是處理content內(nèi)容不變。
/**
* This is the interface for text to which markup objects can be
* attached and detached. Not all Spannable classes have mutable text;
* see {@link Editable} for that.
*/
public interface Spannable
extends Spanned
{
/**
* Attach the specified markup object to the range <code>start…end</code>
* of the text, or move the object to that range if it was already
* attached elsewhere. See {@link Spanned} for an explanation of
* what the flags mean. The object can be one that has meaning only
* within your application, or it can be one that the text system will
* use to affect text display or behavior. Some noteworthy ones are
* the subclasses of {@link android.text.style.CharacterStyle} and
* {@link android.text.style.ParagraphStyle}, and
* {@link android.text.TextWatcher} and
* {@link android.text.SpanWatcher}.
*/
public void setSpan(Object what, int start, int end, int flags);
/**
* Remove the specified object from the range of text to which it
* was attached, if any. It is OK to remove an object that was never
* attached in the first place.
*/
public void removeSpan(Object what);
/**
* Remove the specified object from the range of text to which it
* was attached, if any. It is OK to remove an object that was never
* attached in the first place.
*
* See {@link Spanned} for an explanation of what the flags mean.
*
* @hide
*/
default void removeSpan(Object what, int flags) {
removeSpan(what);
}
/**
* Factory used by TextView to create new {@link Spannable Spannables}. You can subclass
* it to provide something other than {@link SpannableString}.
*
* @see android.widget.TextView#setSpannableFactory(Factory)
*/
public static class Factory {
private static Spannable.Factory sInstance = new Spannable.Factory();
/**
* Returns the standard Spannable Factory.
*/
public static Spannable.Factory getInstance() {
return sInstance;
}
/**
* Returns a new SpannableString from the specified CharSequence.
* You can override this to provide a different kind of Spannable.
*/
public Spannable newSpannable(CharSequence source) {
return new SpannableString(source);
}
}
}
Editable
靜態(tài)單例 實(shí)現(xiàn)工廠方法 返回的SpannableStringBuilder,
This is the interface for text whose content and markup
can be changed
public interface Editable
extends CharSequence, GetChars, Spannable, Appendable
{
/**
* Replaces the specified range (<code>st…en</code>) of text in this
* Editable with a copy of the slice <code>start…end</code> from
* <code>source</code>. The destination slice may be empty, in which case
* the operation is an insertion, or the source slice may be empty,
* in which case the operation is a deletion.
* <p>
* Before the change is committed, each filter that was set with
* {@link #setFilters} is given the opportunity to modify the
* <code>source</code> text.
* <p>
* If <code>source</code>
* is Spanned, the spans from it are preserved into the Editable.
* Existing spans within the Editable that entirely cover the replaced
* range are retained, but any that were strictly within the range
* that was replaced are removed. If the <code>source</code> contains a span
* with {@link Spanned#SPAN_PARAGRAPH} flag, and it does not satisfy the
* paragraph boundary constraint, it is not retained. As a special case, the
* cursor position is preserved even when the entire range where it is located
* is replaced.
* @return a reference to this object.
*
* @see Spanned#SPAN_PARAGRAPH
*/
public Editable replace(int st, int en, CharSequence source, int start, int end);
/**
* Convenience for replace(st, en, text, 0, text.length())
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable replace(int st, int en, CharSequence text);
/**
* Convenience for replace(where, where, text, start, end)
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable insert(int where, CharSequence text, int start, int end);
/**
* Convenience for replace(where, where, text, 0, text.length());
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable insert(int where, CharSequence text);
/**
* Convenience for replace(st, en, "", 0, 0)
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable delete(int st, int en);
/**
* Convenience for replace(length(), length(), text, 0, text.length())
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable append(CharSequence text);
/**
* Convenience for replace(length(), length(), text, start, end)
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable append(CharSequence text, int start, int end);
/**
* Convenience for append(String.valueOf(text)).
* @see #replace(int, int, CharSequence, int, int)
*/
public Editable append(char text);
/**
* Convenience for replace(0, length(), "", 0, 0).
* Note that this clears the text, not the spans;
* use {@link #clearSpans} if you need that.
* @see #replace(int, int, CharSequence, int, int)
*/
public void clear();
/**
* Removes all spans from the Editable, as if by calling
* {@link #removeSpan} on each of them.
*/
public void clearSpans();
/**
* Sets the series of filters that will be called in succession
* whenever the text of this Editable is changed, each of which has
* the opportunity to limit or transform the text that is being inserted.
*/
public void setFilters(InputFilter[] filters);
/**
* Returns the array of input filters that are currently applied
* to changes to this Editable.
*/
public InputFilter[] getFilters();
/**
* Factory used by TextView to create new {@link Editable Editables}. You can subclass
* it to provide something other than {@link SpannableStringBuilder}.
*
* @see android.widget.TextView#setEditableFactory(Factory)
*/
public static class Factory {
private static Editable.Factory sInstance = new Editable.Factory();
/**
* Returns the standard Editable Factory.
*/
public static Editable.Factory getInstance() {
return sInstance;
}
/**
* Returns a new SpannedStringBuilder from the specified
* CharSequence. You can override this to provide
* a different kind of Spanned.
*/
public Editable newEditable(CharSequence source) {
return new SpannableStringBuilder(source);
}
}
}
object what 各種設(shè)置
1 AbsoluteSizeSpan 修改字體大小
//A span that changes the size of the text it's attached to.
public class AbsoluteSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
/**
* Set the text size to <code>size</code> physical pixels.
*/
public AbsoluteSizeSpan(int size) {
this(size, false);
}
/**
* Set the text size to <code>size</code> physical pixels, or to <code>size</code>
* device-independent pixels if <code>dip</code> is true.
*/
public AbsoluteSizeSpan(int size, boolean dip) {
mSize = size;
mDip = dip;
}
/**
* Creates an {@link AbsoluteSizeSpan} from a parcel.
*/
public AbsoluteSizeSpan(@NonNull Parcel src) {
mSize = src.readInt();
mDip = src.readInt() != 0;
}
}
2 BackgroundColorSpan 修改背景色
Changes the background color of the text to which the span is attached.
public class BackgroundColorSpan extends CharacterStyle
implements UpdateAppearance, ParcelableSpan {
/**
* Creates a {@link BackgroundColorSpan} from a color integer.
* <p>
*
* @param color color integer that defines the background color
* @see android.content.res.Resources#getColor(int, Resources.Theme)
*/
public BackgroundColorSpan(@ColorInt int color) {
mColor = color;
}
/**
* Creates a {@link BackgroundColorSpan} from a parcel.
*/
public BackgroundColorSpan(@NonNull Parcel src) {
mColor = src.readInt();
}
}
3 BulletSpan
A span which styles paragraphs as bullet points (respecting layout direction).
設(shè)置小圓點(diǎn)似的符號(hào)
BulletSpans must be attached from the first character to the last character of a single paragraph. otherwise the bullet point will not be displayed but the first paragraph encountered will have a leading margin.
public class BulletSpan implements LeadingMarginSpan, ParcelableSpan {
// Bullet is slightly bigger to avoid aliasing artifacts on mdpi devices.
private static final int STANDARD_BULLET_RADIUS = 4;
public static final int STANDARD_GAP_WIDTH = 2;
private static final int STANDARD_COLOR = 0;
@Px
private final int mGapWidth;
@Px
private final int mBulletRadius;
private Path mBulletPath = null;
@ColorInt
private final int mColor;
private final boolean mWantColor;
/**
* Creates a {@link BulletSpan} with the default values.
*/
public BulletSpan() {
this(STANDARD_GAP_WIDTH, STANDARD_COLOR, false, STANDARD_BULLET_RADIUS);
}
/**
* Creates a {@link BulletSpan} based on a gap width
*
* @param gapWidth the distance, in pixels, between the bullet point and the paragraph.
*/
public BulletSpan(int gapWidth) {
this(gapWidth, STANDARD_COLOR, false, STANDARD_BULLET_RADIUS);
}
/**
* Creates a {@link BulletSpan} based on a gap width and a color integer.
*
* @param gapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param color the bullet point color, as a color integer
* @see android.content.res.Resources#getColor(int, Resources.Theme)
*/
public BulletSpan(int gapWidth, @ColorInt int color) {
this(gapWidth, color, true, STANDARD_BULLET_RADIUS);
}
/**
* Creates a {@link BulletSpan} based on a gap width and a color integer.
*
* @param gapWidth the distance, in pixels, between the bullet point and the paragraph.
* @param color the bullet point color, as a color integer.
* @param bulletRadius the radius of the bullet point, in pixels.
* @see android.content.res.Resources#getColor(int, Resources.Theme)
*/
public BulletSpan(int gapWidth, @ColorInt int color, @IntRange(from = 0) int bulletRadius) {
this(gapWidth, color, true, bulletRadius);
}
private BulletSpan(int gapWidth, @ColorInt int color, boolean wantColor,
@IntRange(from = 0) int bulletRadius) {
mGapWidth = gapWidth;
mBulletRadius = bulletRadius;
mColor = color;
mWantColor = wantColor;
}
/**
* Creates a {@link BulletSpan} from a parcel.
*/
public BulletSpan(@NonNull Parcel src) {
mGapWidth = src.readInt();
mWantColor = src.readInt() != 0;
mColor = src.readInt();
mBulletRadius = src.readInt();
}
}
4 ForegroundColorSpan 設(shè)置文字的顏色
Changes the color of the text to which the span is attached.
SpannableString string = new SpannableString("Text with a foreground color span");
string.setSpan(new ForegroundColorSpan(color), 12, 28, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
5 LeadingMarginSpan.Standard 縮進(jìn)
6 QuoteSpan 文本左側(cè)添加一條豎線
SpannableString string = new SpannableString("Text with quote span on a long line");
string.setSpan(new QuoteSpan(Color.GREEN, 20, 40), 0, string.length(),Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
A span which styles paragraphs by adding a vertical stripe at the beginning of the text (respecting layout direction).
A QuoteSpan must be attached from the first character to the last character of a single paragraph, otherwise the span will not be displayed.
public class QuoteSpan implements LeadingMarginSpan, ParcelableSpan {
public QuoteSpan() {
this(STANDARD_COLOR, STANDARD_STRIPE_WIDTH_PX, STANDARD_GAP_WIDTH_PX);
}
public QuoteSpan(@ColorInt int color) {
this(color, STANDARD_STRIPE_WIDTH_PX, STANDARD_GAP_WIDTH_PX);
}
public QuoteSpan(@ColorInt int color, @IntRange(from = 0) int stripeWidth,
@IntRange(from = 0) int gapWidth) {
mColor = color;
mStripeWidth = stripeWidth;
mGapWidth = gapWidth;
}
public QuoteSpan(@NonNull Parcel src) {
mColor = src.readInt();
mStripeWidth = src.readInt();
mGapWidth = src.readInt();
}
}
7 RelativeSizeSpan 相對(duì)當(dāng)前文本大小進(jìn)行比例縮放
Uniformly scales the size of the text to which it's attached by a certain proportion.
SpannableString string = new SpannableString("Text with relative size span");
string.setSpan(new RelativeSizeSpan(1.5f), 10, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
public class RelativeSizeSpan extends MetricAffectingSpan implements ParcelableSpan {
/**
* Creates a {@link RelativeSizeSpan} based on a proportion.
*
* @param proportion the proportion with which the text is scaled.
*/
public RelativeSizeSpan(@FloatRange(from = 0) float proportion) {
mProportion = proportion;
}
/**
* Creates a {@link RelativeSizeSpan} from a parcel.
*/
public RelativeSizeSpan(@NonNull Parcel src) {
mProportion = src.readFloat();
}
}
8 ScaleXSpan 字體按比例水平方向縮放
Scales horizontally the size of the text to which it's attached by a certain factor.
Values > 1.0 will stretch the text wider. Values < 1.0 will stretch the text narrower.
SpannableString string = new SpannableString("Text with ScaleX span");
string.setSpan(new ScaleXSpan(2f), 10, 16, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
9 StrikethroughSpan 給對(duì)應(yīng)的文本加入刪除線
A span that strikes through the text it's attached to.
SpannableString string = new SpannableString("Text with strikethrough span");
string.setSpan(new StrikethroughSpan(), 10, 23, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
10 StyleSpan 字體的樣式
Span that allows setting the style of the text it's attached to.
Possible styles are: {@link Typeface#NORMAL}, {@link Typeface#BOLD}, {@link Typeface#ITALIC} and
{@link Typeface#BOLD_ITALIC}.
SpannableString string = new SpannableString("Bold and italic text");
string.setSpan(new StyleSpan(Typeface.BOLD), 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new StyleSpan(Typeface.ITALIC), 9, 15, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
11 SubscriptSpan 下標(biāo)式的樣式
The span that moves the position of the text baseline lower.
SpannableString string = new SpannableString("?- C8H10N4O2\n");
string.setSpan(new SubscriptSpan(), 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new SubscriptSpan(), 6, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new SubscriptSpan(), 9, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new SubscriptSpan(), 11, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
12 SuperscriptSpan 上標(biāo)樣式
The span that moves the position of the text baseline higher.
SpannableString string = new SpannableString("1st example");
string.setSpan(new SuperscriptSpan(), 1, 3, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
12 TypefaceSpan 設(shè)置不同的字體
Span that updates the typeface of the text it's attached to
Typeface myTypeface = Typeface.create(ResourcesCompat.getFont(context, R.font.acme),Typeface.BOLD);
SpannableString string = new SpannableString("Text with typeface span.");
string.setSpan(new TypefaceSpan(myTypeface), 1, 8, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new TypefaceSpan("sans-serif"), 10, 18, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
string.setSpan(new TypefaceSpan("monospace"), 19, 22, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
13 UnderlineSpan 下劃線
A span that underlines the text it's attached to.
SpannableString string = new SpannableString("Text with underline span");
string.setSpan(new UnderlineSpan(), 10, 19, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
14 URLSpan 通過(guò)系統(tǒng)瀏覽器打開(kāi)鏈接
Implementation of the {@link ClickableSpan} that allows setting a url string. When selecting and clicking on the text to which the span is attached, the <code>URLSpan</code> will try to open the url, by launching an an Activity with an {@link Intent#ACTION_VIEW} intent.
SpannableString string = new SpannableString("Text with a url span");
string.setSpan(new URLSpan("http://www.baidu.com"), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
URLSpan 實(shí)現(xiàn)部分源碼
public class URLSpan extends ClickableSpan implements ParcelableSpan{
private final String mURL;
public URLSpan(String url) {
mURL = url;
}
public URLSpan(@NonNull Parcel src) {
mURL = src.readString();
}
@Override
public void onClick(View widget) {
Uri uri = Uri.parse(getURL());
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
}
}
}
15 ClickableSpan 抽象類
If an object of this type is attached to the text of a TextView with a movement method of LinkMovementMethod, the affected spans of text can be selected. If selected and clicked, the {@link #onClick} method will be called.
也就是需要實(shí)現(xiàn)點(diǎn)擊效果 必須
textView.setMovementMethod(LinkMovementMethod.getInstance());重寫onClick.
支持下劃線和顏色設(shè)置 重寫 updateDrawState
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
private static int sIdCounter = 0;
private int mId = sIdCounter++;
/**
* Performs the click action associated with this span.
*/
public abstract void onClick(@NonNull View widget);
/**
* Makes the text underlined and in the link color.
*/
@Override
public void updateDrawState(@NonNull TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(true);
}
/**
* Get the unique ID for this span.
*
* @return The unique ID.
* @hide
*/
public int getId() {
return mId;
}
}
16 DrawableMarginSpan
A span which adds a drawable and a padding to the paragraph it's attached to.
If the height of the drawable is bigger than the height of the line it's attached to then the line height is increased to fit the drawable. <code>DrawableMarginSpan</code> allows setting a padding between the drawable and the text. The default value is 0. The span must be set from the beginning of the text, otherwise either the span won't be rendered or it will be rendered incorrectly.
SpannableString string = new SpannableString("Text with a drawable.");
string.setSpan(new DrawableMarginSpan(drawable, 20), 0, string.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
17 IconMarginSpan
類似DrawableMarginSpan 只不過(guò),不過(guò)是加入Bitmap
18 ImageSpan 圖片樣式,主要用于在文本中插入圖片
19 MaskFilterSpan
Span that allows setting a {@link MaskFilter} to the text it's attached to.
文本濾鏡 目前只有模糊效果 BlurMaskFilter 和浮雕效果EmbossMaskFilter
MaskFilter blurMask = new BlurMaskFilter(5f, BlurMaskFilter.Blur.NORMAL);
SpannableString string = new SpannableString("Text with blur mask");
string.setSpan(new MaskFilterSpan(blurMask), 10, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);