来源:http://www.jianshu.com/p/960467ac56c8
都是明白人话不多说,码上开始:
package com.blankj.utilcode.utils;
import android.graphics.Bitmap;
import android.graphics.BlurMaskFilter;
import android.graphics.Typeface;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.support.annotation.ColorInt;
import android.support.annotation.DrawableRes;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.text.Layout.Alignment;
import android.text.SpannableStringBuilder;
import android.text.Spanned; import android.text.style.AlignmentSpan;
import android.text.style.BackgroundColorSpan;
import android.text.style.BulletSpan;
import android.text.style.ClickableSpan;
import android.text.style.ForegroundColorSpan;
import android.text.style.ImageSpan;
import android.text.style.LeadingMarginSpan;
import android.text.style.MaskFilterSpan;
import android.text.style.QuoteSpan;
import android.text.style.RelativeSizeSpan;
import android.text.style.ScaleXSpan;
import android.text.style.StrikethroughSpan;
import android.text.style.StyleSpan;
import android.text.style.SubscriptSpan;
import android.text.style.SuperscriptSpan;
import android.text.style.TypefaceSpan;
import android.text.style.URLSpan;
import android.text.style.UnderlineSpan;
import static android.graphics.BlurMaskFilter.Blur;
public class SpannableStringUtils {
private SpannableStringUtils() {
throw new UnsupportedOperationException("u can't instantiate me...");
}
/** * 获取建造者 * * @return {@link Builder} */
public static Builder getBuilder(@NonNull CharSequence text) {
return new Builder(text);
}
public static class Builder {
private int defaultValue = 0x12000000;
private CharSequence text;
private int flag;
@ColorInt
private int foregroundColor;
@ColorInt
private int backgroundColor;
@ColorInt
private int quoteColor;
private boolean isLeadingMargin;
private int first;
private int rest;
private boolean isBullet;
private int gapWidth;
private int bulletColor;
private float proportion;
private float xProportion;
private boolean isStrikethrough;
private boolean isUnderline;
private boolean isSuperscript;
private boolean isSubscript;
private boolean isBold;
private boolean isItalic;
private boolean isBoldItalic;
private String fontFamily;
private Alignment align;
private boolean imageIsBitmap;
private Bitmap bitmap;
private boolean imageIsDrawable;
private Drawable drawable;
private boolean imageIsUri;
private Uri uri;
private boolean imageIsResourceId;
@DrawableRes
private int resourceId;
private ClickableSpan clickSpan;
private String url;
private boolean isBlur;
private float radius;
private Blur style;
private SpannableStringBuilder mBuilder;
private Builder(@NonNull CharSequence text) {
this.text = text;
flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
foregroundColor = defaultValue;
backgroundColor = defaultValue;
quoteColor = defaultValue;
proportion = -1;
xProportion = -1;
mBuilder = new SpannableStringBuilder();
}
/**
* * 设置标识 * * @param flag
* <ul>
* *
* <li>{@link Spanned#SPAN_INCLUSIVE_EXCLUSIVE}li> *
* <li>{@link Spanned#SPAN_INCLUSIVE_INCLUSIVE}li> *
* <li>{@link Spanned#SPAN_EXCLUSIVE_EXCLUSIVE}li> *
* <li>{@link Spanned#SPAN_EXCLUSIVE_INCLUSIVE}li> *
* ul>
* * @return {@link Builder}
*/
public Builder setFlag(int flag) {
this.flag = flag;
return this;
}
/**
* * 设置前景色 * * @param color 前景色 * @return {@link Builder}
*/
public Builder setForegroundColor(@ColorInt int color) {
this.foregroundColor = color;
return this;
}
/**
* * 设置背景色 *
*
* @param color
* 背景色
* @return {@link Builder}
*/
public Builder setBackgroundColor(@ColorInt int color) {
this.backgroundColor = color;
return this;
}
/**
* 设置引用线的颜色 *
*
* @param color
* 引用线的颜色
* @return {@link Builder}
*/
public Builder setQuoteColor(@ColorInt int color) {
this.quoteColor = color;
return this;
}
/**
* * 设置缩进 * * @param first 首行缩进
*
* @param rest
* 剩余行缩进 * @return {@link Builder}
*/
public Builder setLeadingMargin(int first, int rest) {
this.first = first;
this.rest = rest;
isLeadingMargin = true;
return this;
}
/**
* * 设置列表标记 *
*
* @param gapWidth
* 列表标记和文字间距离 *
* @param color
* 列表标记的颜色 * @return {@link Builder}
*/
public Builder setBullet(int gapWidth, int color) {
this.gapWidth = gapWidth;
bulletColor = color;
isBullet = true;
return this;
}
/**
* * 设置字体比例 * *
*
* @param proportion
* 比例 *
* @return {@link Builder}
*/
public Builder setProportion(float proportion) {
this.proportion = proportion;
return this;
}
/**
* * 设置字体横向比例 * * @param proportion 比例 * @return {@link Builder}
*/
public Builder setXProportion(float proportion) {
this.xProportion = proportion;
return this;
}
/**
* * 设置删除线 *
*
* @return {@link Builder}
*/
public Builder setStrikethrough() {
this.isStrikethrough = true;
return this;
}
/**
* * 设置下划线 * *
*
* @return {@link Builder}
*/
public Builder setUnderline() {
this.isUnderline = true;
return this;
}
/**
* * 设置上标 * *
*
* @return {@link Builder}
*/
public Builder setSuperscript() {
this.isSuperscript = true;
return this;
}
/**
* * 设置下标 *
*
* @return {@link Builder}
*/
public Builder setSubscript() {
this.isSubscript = true;
return this;
}
/**
* * 设置粗体 *
*
* @return {@link Builder}
*/
public Builder setBold() {
isBold = true;
return this;
}
/**
* 设置斜体 *
* @return {@link Builder}
*/
public Builder setItalic() {
isItalic = true;
return this;
}
/** * 设置粗斜体 *
* @return {@link Builder}
*/
public Builder setBoldItalic() {
isBoldItalic = true;
return this;
}
/**
* * 设置字体 * * @param fontFamily 字体 *
* <ul>
* *
* <li>monospaceli> *
* <li>serifli> *
* <li>sans-serifli> *
* ul>
* * @return {@link Builder}
*/
public Builder setFontFamily(@Nullable String fontFamily) {
this.fontFamily = fontFamily;
return this;
}
/**
* * 设置对齐 *
* <ul>
* *
* <li>{@link Alignment#ALIGN_NORMAL}正常li> *
* <li>{@link Alignment#ALIGN_OPPOSITE}相反li> *
* <li>{@link Alignment#ALIGN_CENTER}居中li> *
* ul>
* * * @return {@link Builder}
*/
public Builder setAlign(@Nullable Alignment align) {
this.align = align;
return this;
}
/** * 设置图片 *
* * @param bitmap 图片位图 *
* @return {@link Builder}
*/
public Builder setBitmap(@NonNull Bitmap bitmap) {
this.bitmap = bitmap;
imageIsBitmap = true;
return this;
}
/** * 设置图片 *
* * @param drawable 图片资源 *
* @return {@link Builder}
*/
public Builder setDrawable(@NonNull Drawable drawable) {
this.drawable = drawable;
imageIsDrawable = true;
return this;
}
/** * 设置图片 * *
* @param uri 图片uri *
* @return {@link Builder}
*/
public Builder setUri(@NonNull Uri uri) {
this.uri = uri;
imageIsUri = true;
return this;
}
/** * 设置图片 *
* @param resourceId 图片资源id *
@return {@link Builder}
*/
public Builder setResourceId(@DrawableRes int resourceId) {
this.resourceId = resourceId;
imageIsResourceId = true;
return this;
}
/**
* * 设置点击事件 *
* <p>
* 需添加view.setMovementMethod(LinkMovementMethod.getInstance())
* p>
* * @param clickSpan 点击事件 * @return {@link Builder}
*/
public Builder setClickSpan(@NonNull ClickableSpan clickSpan) {
this.clickSpan = clickSpan;
return this;
}
/**
* * 设置超链接 *
* <p>
* 需添加view.setMovementMethod(LinkMovementMethod.getInstance())
* p>
* * * @param url 超链接 * @return {@link Builder}
*/
public Builder setUrl(@NonNull String url) {
this.url = url;
return this;
}
/**
* * 设置模糊 *
* <p>
* 尚存bug,其他地方存在相同的字体的话,相同字体出现在之前的话那么就不会模糊,出现在之后的话那会一起模糊
* p>
* *
* <p>
* 推荐还是把所有字体都模糊这样使用
* p>
* * * @param radius 模糊半径(需大于0) * @param style 模糊样式
* <ul>
* *
* <li>{@link Blur#NORMAL}li> *
* <li>{@link Blur#SOLID}li> *
* <li>{@link Blur#OUTER}li> *
* <li>{@link Blur#INNER}li> *
* ul>
* * @return {@link Builder}
*/
public Builder setBlur(float radius, Blur style) {
this.radius = radius;
this.style = style;
this.isBlur = true;
return this;
}
/** *
* 追加样式字符串 *
* * @param text 样式字符串文本 *
* @return {@link Builder}
*/
public Builder append(@NonNull CharSequence text) {
setSpan();
this.text = text;
return this;
}
/** * 创建样式字符串 *
* @return 样式字符串
*/
public SpannableStringBuilder create() {
setSpan();
return mBuilder;
}
/**
* * 设置样式
*/
private void setSpan() {
int start = mBuilder.length();
mBuilder.append(this.text);
int end = mBuilder.length();
if (foregroundColor != defaultValue) {
mBuilder.setSpan(new ForegroundColorSpan(foregroundColor),start, end, flag);
foregroundColor = defaultValue;
if (backgroundColor != defaultValue) {
mBuilder.setSpan(new BackgroundColorSpan(backgroundColor),start, end, flag);
backgroundColor = defaultValue;
}
if (isLeadingMargin) {
mBuilder.setSpan(new LeadingMarginSpan.Standard(first, rest),start, end, flag);
isLeadingMargin = false;
if (quoteColor != defaultValue) {
mBuilder.setSpan(new QuoteSpan(quoteColor), start, end, 0);
quoteColor = defaultValue;
}
if (isBullet) {
mBuilder.setSpan(new BulletSpan(gapWidth, bulletColor), start,end, 0);
isBullet = false;
if (proportion != -1) {
mBuilder.setSpan(new RelativeSizeSpan(proportion), start, end,flag);
proportion = -1;
}
if (xProportion != -1) {
mBuilder.setSpan(new ScaleXSpan(xProportion), start, end, flag);
xProportion = -1;
if (isStrikethrough) {
mBuilder.setSpan(new StrikethroughSpan(), start, end, flag);
isStrikethrough = false;
}
if (isUnderline) {
mBuilder.setSpan(new UnderlineSpan(), start, end, flag);
isUnderline = false;
if (isSuperscript) {
mBuilder.setSpan(new SuperscriptSpan(), start, end, flag);
isSuperscript = false;
}
if (isSubscript) {
mBuilder.setSpan(new SubscriptSpan(), start, end, flag);
isSubscript = false;
if (isBold) {
mBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, flag);
isBold = false;
}
if (isItalic) {
mBuilder.setSpan(new StyleSpan(Typeface.ITALIC), start, end,flag);
isItalic = false;
if (isBoldItalic) {
mBuilder.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), start,end, flag);
isBoldItalic = false;
}
if (fontFamily != null) {
mBuilder.setSpan(new TypefaceSpan(fontFamily), start, end, flag);
fontFamily = null;
if (align != null) {
mBuilder.setSpan(new AlignmentSpan.Standard(align), start, end,flag);
align = null;
}
if (imageIsBitmap || imageIsDrawable || imageIsUri
|| imageIsResourceId) {
if (imageIsBitmap) {
mBuilder.setSpan(new ImageSpan(Utils.context, bitmap),
start, end, flag);
bitmap = null;
imageIsBitmap = false;
} else if (imageIsDrawable) {
mBuilder.setSpan(new ImageSpan(drawable), start, end, flag);
drawable = null;
imageIsDrawable = false;
} else if (imageIsUri) {
mBuilder.setSpan(new ImageSpan(Utils.context, uri), start,end, flag);
uri = null;
imageIsUri = false;
} else {
mBuilder.setSpan(new ImageSpan(Utils.context, resourceId),start, end, flag);
resourceId = 0;
imageIsResourceId = false;
}
}
if (clickSpan != null) {
mBuilder.setSpan(clickSpan, start, end, flag);
clickSpan = null;
}
if (url != null) {
mBuilder.setSpan(new URLSpan(url), start, end, flag);
url = null;
}
if (isBlur) {
mBuilder.setSpan(newMaskFilterSpan(new BlurMaskFilter(radius,style)), start, end, flag);
isBlur = false;
}
flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
}
}
}
心动了赶紧就去试试吧!这只是一个起到参照作用,实际工作中可以根据不同的需求来完善其功能。