diff --git a/Lib_Base/src/main/java/com/quyunshuo/base/utils/SpannableStringUtils.java b/Lib_Base/src/main/java/com/quyunshuo/base/utils/SpannableStringUtils.java
deleted file mode 100644
index f9bc6c0..0000000
--- a/Lib_Base/src/main/java/com/quyunshuo/base/utils/SpannableStringUtils.java
+++ /dev/null
@@ -1,1505 +0,0 @@
-package com.quyunshuo.base.utils;
-
-import android.annotation.SuppressLint;
-import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.BlurMaskFilter;
-import android.graphics.Canvas;
-import android.graphics.Color;
-import android.graphics.Paint;
-import android.graphics.Path;
-import android.graphics.Rect;
-import android.graphics.Shader;
-import android.graphics.Typeface;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.drawable.Drawable;
-import android.net.Uri;
-import android.text.Layout;
-import android.text.Layout.Alignment;
-import android.text.SpannableStringBuilder;
-import android.text.Spanned;
-import android.text.TextPaint;
-import android.text.method.LinkMovementMethod;
-import android.text.style.AbsoluteSizeSpan;
-import android.text.style.AlignmentSpan;
-import android.text.style.BackgroundColorSpan;
-import android.text.style.CharacterStyle;
-import android.text.style.ClickableSpan;
-import android.text.style.ForegroundColorSpan;
-import android.text.style.LeadingMarginSpan;
-import android.text.style.LineHeightSpan;
-import android.text.style.MaskFilterSpan;
-import android.text.style.RelativeSizeSpan;
-import android.text.style.ReplacementSpan;
-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 android.text.style.UpdateAppearance;
-import android.util.Log;
-import android.view.View;
-import android.widget.TextView;
-
-import androidx.annotation.ColorInt;
-import androidx.annotation.DrawableRes;
-import androidx.annotation.FloatRange;
-import androidx.annotation.IntDef;
-import androidx.annotation.IntRange;
-import androidx.annotation.NonNull;
-import androidx.annotation.Nullable;
-import androidx.core.content.ContextCompat;
-
-import com.quyunshuo.base.BaseApplication;
-
-import java.io.InputStream;
-import java.io.Serializable;
-import java.lang.annotation.Retention;
-import java.lang.annotation.RetentionPolicy;
-import java.lang.ref.WeakReference;
-
-import static android.graphics.BlurMaskFilter.Blur;
-
-/**
- * @Author: QuYunShuo
- * @Time: 2020/9/17
- * @Class: SpannableStringUtils
- * @Remark: 字符串相关
- * 相关方法:
- *
- * with() : 设置控件
- * setFlag() : 设置标识
- * setForegroundColor(): 设置前景色
- * setBackgroundColor(): 设置背景色
- * setLineHeight() : 设置行高
- * setQuoteColor() : 设置引用线的颜色
- * setLeadingMargin() : 设置缩进
- * setBullet() : 设置列表标记
- * setFontSize() : 设置字体尺寸
- * setFontProportion() : 设置字体比例
- * setFontXProportion(): 设置字体横向比例
- * setStrikethrough() : 设置删除线
- * setUnderline() : 设置下划线
- * setSuperscript() : 设置上标
- * setSubscript() : 设置下标
- * setBold() : 设置粗体
- * setItalic() : 设置斜体
- * setBoldItalic() : 设置粗斜体
- * setFontFamily() : 设置字体系列
- * setTypeface() : 设置字体
- * setAlign() : 设置对齐
- * setClickSpan() : 设置点击事件
- * setUrl() : 设置超链接
- * setBlur() : 设置模糊
- * setShader() : 设置着色器
- * setShadow() : 设置阴影
- * setSpans() : 设置样式
- * append() : 追加样式字符串
- * appendLine() : 追加一行样式字符串
- * appendImage() : 追加图片
- * appendSpace() : 追加空白
- * create() : 创建样式字符串
- *
- * 示例:
- *
- * SpanUtils.with(TextView)
- * .append("String")
- * .append("String")
- * .setForegroundColor(ContextCompat.getColor(getContext(), R.color.color666666))
- * .setFontSize(14, true)
- * .create();
- *
- */
-public final class SpannableStringUtils {
-
- private static final int COLOR_DEFAULT = 0xFEFFFFFF;
-
- public static final int ALIGN_BOTTOM = 0;
- public static final int ALIGN_BASELINE = 1;
- public static final int ALIGN_CENTER = 2;
- public static final int ALIGN_TOP = 3;
-
- @IntDef({ALIGN_BOTTOM, ALIGN_BASELINE, ALIGN_CENTER, ALIGN_TOP})
- @Retention(RetentionPolicy.SOURCE)
- public @interface Align {
- }
-
- private static final String LINE_SEPARATOR = System.getProperty("line.separator");
-
- public static SpannableStringUtils with(final TextView textView) {
- return new SpannableStringUtils(textView);
- }
-
- private TextView mTextView;
- private CharSequence mText;
- private int flag;
- private int foregroundColor;
- private int backgroundColor;
- private int lineHeight;
- private int alignLine;
- private int quoteColor;
- private int stripeWidth;
- private int quoteGapWidth;
- private int first;
- private int rest;
- private int bulletColor;
- private int bulletRadius;
- private int bulletGapWidth;
- private int fontSize;
- private boolean fontSizeIsDp;
- 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 Typeface typeface;
- private Alignment alignment;
- private int verticalAlign;
- private ClickableSpan clickSpan;
- private String url;
- private float blurRadius;
- private Blur style;
- private Shader shader;
- private float shadowRadius;
- private float shadowDx;
- private float shadowDy;
- private int shadowColor;
- private Object[] spans;
-
- private Bitmap imageBitmap;
- private Drawable imageDrawable;
- private Uri imageUri;
- private int imageResourceId;
- private int alignImage;
-
- private int spaceSize;
- private int spaceColor;
-
- private SerializableSpannableStringBuilder mBuilder;
- private boolean isCreated;
-
- private int mType;
- private final int mTypeCharSequence = 0;
- private final int mTypeImage = 1;
- private final int mTypeSpace = 2;
-
- private SpannableStringUtils(TextView textView) {
- this();
- mTextView = textView;
- }
-
- public SpannableStringUtils() {
- mBuilder = new SerializableSpannableStringBuilder();
- mText = "";
- mType = -1;
- setDefault();
- }
-
- private void setDefault() {
- flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
- foregroundColor = COLOR_DEFAULT;
- backgroundColor = COLOR_DEFAULT;
- lineHeight = -1;
- quoteColor = COLOR_DEFAULT;
- first = -1;
- bulletColor = COLOR_DEFAULT;
- fontSize = -1;
- proportion = -1;
- xProportion = -1;
- isStrikethrough = false;
- isUnderline = false;
- isSuperscript = false;
- isSubscript = false;
- isBold = false;
- isItalic = false;
- isBoldItalic = false;
- fontFamily = null;
- typeface = null;
- alignment = null;
- verticalAlign = -1;
- clickSpan = null;
- url = null;
- blurRadius = -1;
- shader = null;
- shadowRadius = -1;
- spans = null;
-
- imageBitmap = null;
- imageDrawable = null;
- imageUri = null;
- imageResourceId = -1;
-
- spaceSize = -1;
- }
-
- /**
- * Set the span of flag.
- *
- * @param flag The flag.
- *
- * - {@link Spanned#SPAN_INCLUSIVE_EXCLUSIVE}
- * - {@link Spanned#SPAN_INCLUSIVE_INCLUSIVE}
- * - {@link Spanned#SPAN_EXCLUSIVE_EXCLUSIVE}
- * - {@link Spanned#SPAN_EXCLUSIVE_INCLUSIVE}
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFlag(final int flag) {
- this.flag = flag;
- return this;
- }
-
- /**
- * Set the span of foreground's color.
- *
- * @param color The color of foreground
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setForegroundColor(@ColorInt final int color) {
- this.foregroundColor = color;
- return this;
- }
-
- /**
- * Set the span of background's color.
- *
- * @param color The color of background
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBackgroundColor(@ColorInt final int color) {
- this.backgroundColor = color;
- return this;
- }
-
- /**
- * Set the span of line height.
- *
- * @param lineHeight The line height, in pixel.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setLineHeight(@IntRange(from = 0) final int lineHeight) {
- return setLineHeight(lineHeight, ALIGN_CENTER);
- }
-
- /**
- * Set the span of line height.
- *
- * @param lineHeight The line height, in pixel.
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER}
- * - {@link Align#ALIGN_BOTTOM}
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setLineHeight(@IntRange(from = 0) final int lineHeight,
- @Align final int align) {
- this.lineHeight = lineHeight;
- this.alignLine = align;
- return this;
- }
-
- /**
- * Set the span of quote's color.
- *
- * @param color The color of quote
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setQuoteColor(@ColorInt final int color) {
- return setQuoteColor(color, 2, 2);
- }
-
- /**
- * Set the span of quote's color.
- *
- * @param color The color of quote.
- * @param stripeWidth The width of stripe, in pixel.
- * @param gapWidth The width of gap, in pixel.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setQuoteColor(@ColorInt final int color,
- @IntRange(from = 1) final int stripeWidth,
- @IntRange(from = 0) final int gapWidth) {
- this.quoteColor = color;
- this.stripeWidth = stripeWidth;
- this.quoteGapWidth = gapWidth;
- return this;
- }
-
- /**
- * Set the span of leading margin.
- *
- * @param first The indent for the first line of the paragraph.
- * @param rest The indent for the remaining lines of the paragraph.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setLeadingMargin(@IntRange(from = 0) final int first,
- @IntRange(from = 0) final int rest) {
- this.first = first;
- this.rest = rest;
- return this;
- }
-
- /**
- * Set the span of bullet.
- *
- * @param gapWidth The width of gap, in pixel.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBullet(@IntRange(from = 0) final int gapWidth) {
- return setBullet(0, 3, gapWidth);
- }
-
- /**
- * Set the span of bullet.
- *
- * @param color The color of bullet.
- * @param radius The radius of bullet, in pixel.
- * @param gapWidth The width of gap, in pixel.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBullet(@ColorInt final int color,
- @IntRange(from = 0) final int radius,
- @IntRange(from = 0) final int gapWidth) {
- this.bulletColor = color;
- this.bulletRadius = radius;
- this.bulletGapWidth = gapWidth;
- return this;
- }
-
- /**
- * Set the span of font's size.
- *
- * @param size The size of font.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFontSize(@IntRange(from = 0) final int size) {
- return setFontSize(size, false);
- }
-
- /**
- * Set the span of size of font.
- *
- * @param size The size of font.
- * @param isSp True to use sp, false to use pixel.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFontSize(@IntRange(from = 0) final int size, final boolean isSp) {
- this.fontSize = size;
- this.fontSizeIsDp = isSp;
- return this;
- }
-
- /**
- * Set the span of proportion of font.
- *
- * @param proportion The proportion of font.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFontProportion(final float proportion) {
- this.proportion = proportion;
- return this;
- }
-
- /**
- * Set the span of transverse proportion of font.
- *
- * @param proportion The transverse proportion of font.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFontXProportion(final float proportion) {
- this.xProportion = proportion;
- return this;
- }
-
- /**
- * Set the span of strikethrough.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setStrikethrough() {
- this.isStrikethrough = true;
- return this;
- }
-
- /**
- * Set the span of underline.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setUnderline() {
- this.isUnderline = true;
- return this;
- }
-
- /**
- * Set the span of superscript.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setSuperscript() {
- this.isSuperscript = true;
- return this;
- }
-
- /**
- * Set the span of subscript.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setSubscript() {
- this.isSubscript = true;
- return this;
- }
-
- /**
- * Set the span of bold.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBold() {
- isBold = true;
- return this;
- }
-
- /**
- * Set the span of italic.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setItalic() {
- isItalic = true;
- return this;
- }
-
- /**
- * Set the span of bold italic.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBoldItalic() {
- isBoldItalic = true;
- return this;
- }
-
- /**
- * Set the span of font family.
- *
- * @param fontFamily The font family.
- *
- * - monospace
- * - serif
- * - sans-serif
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setFontFamily(@NonNull final String fontFamily) {
- this.fontFamily = fontFamily;
- return this;
- }
-
- /**
- * Set the span of typeface.
- *
- * @param typeface The typeface.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setTypeface(@NonNull final Typeface typeface) {
- this.typeface = typeface;
- return this;
- }
-
- /**
- * Set the span of horizontal alignment.
- *
- * @param alignment The alignment.
- *
- * - {@link Alignment#ALIGN_NORMAL }
- * - {@link Alignment#ALIGN_OPPOSITE}
- * - {@link Alignment#ALIGN_CENTER }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setHorizontalAlign(@NonNull final Alignment alignment) {
- this.alignment = alignment;
- return this;
- }
-
- /**
- * Set the span of vertical alignment.
- *
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER }
- * - {@link Align#ALIGN_BASELINE}
- * - {@link Align#ALIGN_BOTTOM }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setVerticalAlign(@Align final int align) {
- this.verticalAlign = align;
- return this;
- }
-
- /**
- * Set the span of click.
- * Must set {@code view.setMovementMethod(LinkMovementMethod.getInstance())}
- *
- * @param clickSpan The span of click.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setClickSpan(@NonNull final ClickableSpan clickSpan) {
- if (mTextView != null && mTextView.getMovementMethod() == null) {
- mTextView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- this.clickSpan = clickSpan;
- return this;
- }
-
- /**
- * Set the span of click.
- * Must set {@code view.setMovementMethod(LinkMovementMethod.getInstance())}
- *
- * @param color The color of click span.
- * @param underlineText True to support underline, false otherwise.
- * @param listener The listener of click span.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setClickSpan(@ColorInt final int color,
- final boolean underlineText,
- final View.OnClickListener listener) {
- if (mTextView != null && mTextView.getMovementMethod() == null) {
- mTextView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- this.clickSpan = new ClickableSpan() {
-
- @Override
- public void updateDrawState(@NonNull TextPaint paint) {
- paint.setColor(color);
- paint.setUnderlineText(underlineText);
- }
-
- @Override
- public void onClick(@NonNull View widget) {
- if (listener != null) {
- listener.onClick(widget);
- }
- }
- };
- return this;
- }
-
- /**
- * Set the span of url.
- * Must set {@code view.setMovementMethod(LinkMovementMethod.getInstance())}
- *
- * @param url The url.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setUrl(@NonNull final String url) {
- if (mTextView != null && mTextView.getMovementMethod() == null) {
- mTextView.setMovementMethod(LinkMovementMethod.getInstance());
- }
- this.url = url;
- return this;
- }
-
- /**
- * Set the span of blur.
- *
- * @param radius The radius of blur.
- * @param style The style.
- *
- * - {@link Blur#NORMAL}
- * - {@link Blur#SOLID}
- * - {@link Blur#OUTER}
- * - {@link Blur#INNER}
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setBlur(@FloatRange(from = 0, fromInclusive = false) final float radius,
- final Blur style) {
- this.blurRadius = radius;
- this.style = style;
- return this;
- }
-
- /**
- * Set the span of shader.
- *
- * @param shader The shader.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setShader(@NonNull final Shader shader) {
- this.shader = shader;
- return this;
- }
-
- /**
- * Set the span of shadow.
- *
- * @param radius The radius of shadow.
- * @param dx X-axis offset, in pixel.
- * @param dy Y-axis offset, in pixel.
- * @param shadowColor The color of shadow.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setShadow(@FloatRange(from = 0, fromInclusive = false) final float radius,
- final float dx,
- final float dy,
- final int shadowColor) {
- this.shadowRadius = radius;
- this.shadowDx = dx;
- this.shadowDy = dy;
- this.shadowColor = shadowColor;
- return this;
- }
-
-
- /**
- * Set the spans.
- *
- * @param spans The spans.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils setSpans(@NonNull final Object... spans) {
- if (spans.length > 0) {
- this.spans = spans;
- }
- return this;
- }
-
- /**
- * Append the text text.
- *
- * @param text The text.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils append(@NonNull final CharSequence text) {
- apply(mTypeCharSequence);
- mText = text;
- return this;
- }
-
- /**
- * Append one line.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendLine() {
- apply(mTypeCharSequence);
- mText = LINE_SEPARATOR;
- return this;
- }
-
- /**
- * Append text and one line.
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendLine(@NonNull final CharSequence text) {
- apply(mTypeCharSequence);
- mText = text + LINE_SEPARATOR;
- return this;
- }
-
- /**
- * Append one image.
- *
- * @param bitmap The bitmap of image.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Bitmap bitmap) {
- return appendImage(bitmap, ALIGN_BOTTOM);
- }
-
- /**
- * Append one image.
- *
- * @param bitmap The bitmap.
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER }
- * - {@link Align#ALIGN_BASELINE}
- * - {@link Align#ALIGN_BOTTOM }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Bitmap bitmap, @Align final int align) {
- apply(mTypeImage);
- this.imageBitmap = bitmap;
- this.alignImage = align;
- return this;
- }
-
- /**
- * Append one image.
- *
- * @param drawable The drawable of image.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Drawable drawable) {
- return appendImage(drawable, ALIGN_BOTTOM);
- }
-
- /**
- * Append one image.
- *
- * @param drawable The drawable of image.
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER }
- * - {@link Align#ALIGN_BASELINE}
- * - {@link Align#ALIGN_BOTTOM }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Drawable drawable, @Align final int align) {
- apply(mTypeImage);
- this.imageDrawable = drawable;
- this.alignImage = align;
- return this;
- }
-
- /**
- * Append one image.
- *
- * @param uri The uri of image.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Uri uri) {
- return appendImage(uri, ALIGN_BOTTOM);
- }
-
- /**
- * Append one image.
- *
- * @param uri The uri of image.
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER }
- * - {@link Align#ALIGN_BASELINE}
- * - {@link Align#ALIGN_BOTTOM }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@NonNull final Uri uri, @Align final int align) {
- apply(mTypeImage);
- this.imageUri = uri;
- this.alignImage = align;
- return this;
- }
-
- /**
- * Append one image.
- *
- * @param resourceId The resource id of image.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@DrawableRes final int resourceId) {
- return appendImage(resourceId, ALIGN_BOTTOM);
- }
-
- /**
- * Append one image.
- *
- * @param resourceId The resource id of image.
- * @param align The alignment.
- *
- * - {@link Align#ALIGN_TOP }
- * - {@link Align#ALIGN_CENTER }
- * - {@link Align#ALIGN_BASELINE}
- * - {@link Align#ALIGN_BOTTOM }
- *
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendImage(@DrawableRes final int resourceId, @Align final int align) {
- apply(mTypeImage);
- this.imageResourceId = resourceId;
- this.alignImage = align;
- return this;
- }
-
- /**
- * Append space.
- *
- * @param size The size of space.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendSpace(@IntRange(from = 0) final int size) {
- return appendSpace(size, Color.TRANSPARENT);
- }
-
- /**
- * Append space.
- *
- * @param size The size of space.
- * @param color The color of space.
- * @return the single {@link SpannableStringUtils} instance
- */
- public SpannableStringUtils appendSpace(@IntRange(from = 0) final int size, @ColorInt final int color) {
- apply(mTypeSpace);
- spaceSize = size;
- spaceColor = color;
- return this;
- }
-
- private void apply(final int type) {
- applyLast();
- mType = type;
- }
-
- public SpannableStringBuilder get() {
- return mBuilder;
- }
-
- /**
- * Create the span string.
- *
- * @return the span string
- */
- public SpannableStringBuilder create() {
- applyLast();
- if (mTextView != null) {
- mTextView.setText(mBuilder);
- }
- isCreated = true;
- return mBuilder;
- }
-
- private void applyLast() {
- if (isCreated) {
- return;
- }
- if (mType == mTypeCharSequence) {
- updateCharCharSequence();
- } else if (mType == mTypeImage) {
- updateImage();
- } else if (mType == mTypeSpace) {
- updateSpace();
- }
- setDefault();
- }
-
- private void updateCharCharSequence() {
- if (mText.length() == 0) return;
- int start = mBuilder.length();
- if (start == 0 && lineHeight != -1) {// bug of LineHeightSpan when first line
- mBuilder.append(Character.toString((char) 2))
- .append("\n")
- .setSpan(new AbsoluteSizeSpan(0), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
- start = 2;
- }
- mBuilder.append(mText);
- int end = mBuilder.length();
- if (verticalAlign != -1) {
- mBuilder.setSpan(new VerticalAlignSpan(verticalAlign), start, end, flag);
- }
- if (foregroundColor != COLOR_DEFAULT) {
- mBuilder.setSpan(new ForegroundColorSpan(foregroundColor), start, end, flag);
- }
- if (backgroundColor != COLOR_DEFAULT) {
- mBuilder.setSpan(new BackgroundColorSpan(backgroundColor), start, end, flag);
- }
- if (first != -1) {
- mBuilder.setSpan(new LeadingMarginSpan.Standard(first, rest), start, end, flag);
- }
- if (quoteColor != COLOR_DEFAULT) {
- mBuilder.setSpan(
- new CustomQuoteSpan(quoteColor, stripeWidth, quoteGapWidth),
- start,
- end,
- flag
- );
- }
- if (bulletColor != COLOR_DEFAULT) {
- mBuilder.setSpan(
- new CustomBulletSpan(bulletColor, bulletRadius, bulletGapWidth),
- start,
- end,
- flag
- );
- }
- if (fontSize != -1) {
- mBuilder.setSpan(new AbsoluteSizeSpan(fontSize, fontSizeIsDp), start, end, flag);
- }
- if (proportion != -1) {
- mBuilder.setSpan(new RelativeSizeSpan(proportion), start, end, flag);
- }
- if (xProportion != -1) {
- mBuilder.setSpan(new ScaleXSpan(xProportion), start, end, flag);
- }
- if (lineHeight != -1) {
- mBuilder.setSpan(new CustomLineHeightSpan(lineHeight, alignLine), start, end, flag);
- }
- if (isStrikethrough) {
- mBuilder.setSpan(new StrikethroughSpan(), start, end, flag);
- }
- if (isUnderline) {
- mBuilder.setSpan(new UnderlineSpan(), start, end, flag);
- }
- if (isSuperscript) {
- mBuilder.setSpan(new SuperscriptSpan(), start, end, flag);
- }
- if (isSubscript) {
- mBuilder.setSpan(new SubscriptSpan(), start, end, flag);
- }
- if (isBold) {
- mBuilder.setSpan(new StyleSpan(Typeface.BOLD), start, end, flag);
- }
- if (isItalic) {
- mBuilder.setSpan(new StyleSpan(Typeface.ITALIC), start, end, flag);
- }
- if (isBoldItalic) {
- mBuilder.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), start, end, flag);
- }
- if (fontFamily != null) {
- mBuilder.setSpan(new TypefaceSpan(fontFamily), start, end, flag);
- }
- if (typeface != null) {
- mBuilder.setSpan(new CustomTypefaceSpan(typeface), start, end, flag);
- }
- if (alignment != null) {
- mBuilder.setSpan(new AlignmentSpan.Standard(alignment), start, end, flag);
- }
- if (clickSpan != null) {
- mBuilder.setSpan(clickSpan, start, end, flag);
- }
- if (url != null) {
- mBuilder.setSpan(new URLSpan(url), start, end, flag);
- }
- if (blurRadius != -1) {
- mBuilder.setSpan(
- new MaskFilterSpan(new BlurMaskFilter(blurRadius, style)),
- start,
- end,
- flag
- );
- }
- if (shader != null) {
- mBuilder.setSpan(new ShaderSpan(shader), start, end, flag);
- }
- if (shadowRadius != -1) {
- mBuilder.setSpan(
- new ShadowSpan(shadowRadius, shadowDx, shadowDy, shadowColor),
- start,
- end,
- flag
- );
- }
- if (spans != null) {
- for (Object span : spans) {
- mBuilder.setSpan(span, start, end, flag);
- }
- }
- }
-
- private void updateImage() {
- int start = mBuilder.length();
- mText = "
";
- updateCharCharSequence();
- int end = mBuilder.length();
- if (imageBitmap != null) {
- mBuilder.setSpan(new CustomImageSpan(imageBitmap, alignImage), start, end, flag);
- } else if (imageDrawable != null) {
- mBuilder.setSpan(new CustomImageSpan(imageDrawable, alignImage), start, end, flag);
- } else if (imageUri != null) {
- mBuilder.setSpan(new CustomImageSpan(imageUri, alignImage), start, end, flag);
- } else if (imageResourceId != -1) {
- mBuilder.setSpan(new CustomImageSpan(imageResourceId, alignImage), start, end, flag);
- }
- }
-
- private void updateSpace() {
- int start = mBuilder.length();
- mText = "< >";
- updateCharCharSequence();
- int end = mBuilder.length();
- mBuilder.setSpan(new SpaceSpan(spaceSize, spaceColor), start, end, flag);
- }
-
- static class VerticalAlignSpan extends ReplacementSpan {
-
- static final int ALIGN_CENTER = 2;
- static final int ALIGN_TOP = 3;
-
- final int mVerticalAlignment;
-
- VerticalAlignSpan(int verticalAlignment) {
- mVerticalAlignment = verticalAlignment;
- }
-
- @Override
- public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
- text = text.subSequence(start, end);
- return (int) paint.measureText(text.toString());
- }
-
- @Override
- public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
- text = text.subSequence(start, end);
- Paint.FontMetricsInt fm = paint.getFontMetricsInt();
-// int need = height - (v + fm.descent - fm.ascent - spanstartv);
-// if (need > 0) {
-// if (mVerticalAlignment == ALIGN_TOP) {
-// fm.descent += need;
-// } else if (mVerticalAlignment == ALIGN_CENTER) {
-// fm.descent += need / 2;
-// fm.ascent -= need / 2;
-// } else {
-// fm.ascent -= need;
-// }
-// }
-// need = height - (v + fm.bottom - fm.top - spanstartv);
-// if (need > 0) {
-// if (mVerticalAlignment == ALIGN_TOP) {
-// fm.bottom += need;
-// } else if (mVerticalAlignment == ALIGN_CENTER) {
-// fm.bottom += need / 2;
-// fm.top -= need / 2;
-// } else {
-// fm.top -= need;
-// }
-// }
-
- canvas.drawText(text.toString(), x, y - ((y + fm.descent + y + fm.ascent) / 2 - (bottom + top) / 2), paint);
- }
- }
-
- static class CustomLineHeightSpan implements LineHeightSpan {
-
- private final int height;
-
- static final int ALIGN_CENTER = 2;
- static final int ALIGN_TOP = 3;
-
- final int mVerticalAlignment;
- static Paint.FontMetricsInt sfm;
-
- CustomLineHeightSpan(int height, int verticalAlignment) {
- this.height = height;
- mVerticalAlignment = verticalAlignment;
- }
-
- @Override
- public void chooseHeight(final CharSequence text, final int start, final int end,
- final int spanstartv, final int v, final Paint.FontMetricsInt fm) {
-// LogUtils.e(fm, sfm);
- if (sfm == null) {
- sfm = new Paint.FontMetricsInt();
- sfm.top = fm.top;
- sfm.ascent = fm.ascent;
- sfm.descent = fm.descent;
- sfm.bottom = fm.bottom;
- sfm.leading = fm.leading;
- } else {
- fm.top = sfm.top;
- fm.ascent = sfm.ascent;
- fm.descent = sfm.descent;
- fm.bottom = sfm.bottom;
- fm.leading = sfm.leading;
- }
- int need = height - (v + fm.descent - fm.ascent - spanstartv);
- if (need > 0) {
- if (mVerticalAlignment == ALIGN_TOP) {
- fm.descent += need;
- } else if (mVerticalAlignment == ALIGN_CENTER) {
- fm.descent += need / 2;
- fm.ascent -= need / 2;
- } else {
- fm.ascent -= need;
- }
- }
- need = height - (v + fm.bottom - fm.top - spanstartv);
- if (need > 0) {
- if (mVerticalAlignment == ALIGN_TOP) {
- fm.bottom += need;
- } else if (mVerticalAlignment == ALIGN_CENTER) {
- fm.bottom += need / 2;
- fm.top -= need / 2;
- } else {
- fm.top -= need;
- }
- }
- if (end == ((Spanned) text).getSpanEnd(this)) {
- sfm = null;
- }
-// LogUtils.e(fm, sfm);
- }
- }
-
- static class SpaceSpan extends ReplacementSpan {
-
- private final int width;
- private final Paint paint = new Paint();
-
- private SpaceSpan(final int width) {
- this(width, Color.TRANSPARENT);
- }
-
- private SpaceSpan(final int width, final int color) {
- super();
- this.width = width;
- paint.setColor(color);
- paint.setStyle(Paint.Style.FILL);
- }
-
- @Override
- public int getSize(@NonNull final Paint paint, final CharSequence text,
- @IntRange(from = 0) final int start,
- @IntRange(from = 0) final int end,
- @Nullable final Paint.FontMetricsInt fm) {
- return width;
- }
-
- @Override
- public void draw(@NonNull final Canvas canvas, final CharSequence text,
- @IntRange(from = 0) final int start,
- @IntRange(from = 0) final int end,
- final float x, final int top, final int y, final int bottom,
- @NonNull final Paint paint) {
- canvas.drawRect(x, top, x + width, bottom, this.paint);
- }
- }
-
- static class CustomQuoteSpan implements LeadingMarginSpan {
-
- private final int color;
- private final int stripeWidth;
- private final int gapWidth;
-
- private CustomQuoteSpan(final int color, final int stripeWidth, final int gapWidth) {
- super();
- this.color = color;
- this.stripeWidth = stripeWidth;
- this.gapWidth = gapWidth;
- }
-
- public int getLeadingMargin(final boolean first) {
- return stripeWidth + gapWidth;
- }
-
- public void drawLeadingMargin(final Canvas c, final Paint p, final int x, final int dir,
- final int top, final int baseline, final int bottom,
- final CharSequence text, final int start, final int end,
- final boolean first, final Layout layout) {
- Paint.Style style = p.getStyle();
- int color = p.getColor();
-
- p.setStyle(Paint.Style.FILL);
- p.setColor(this.color);
-
- c.drawRect(x, top, x + dir * stripeWidth, bottom, p);
-
- p.setStyle(style);
- p.setColor(color);
- }
- }
-
- static class CustomBulletSpan implements LeadingMarginSpan {
-
- private final int color;
- private final int radius;
- private final int gapWidth;
-
- private Path sBulletPath = null;
-
- private CustomBulletSpan(final int color, final int radius, final int gapWidth) {
- this.color = color;
- this.radius = radius;
- this.gapWidth = gapWidth;
- }
-
- public int getLeadingMargin(final boolean first) {
- return 2 * radius + gapWidth;
- }
-
- public void drawLeadingMargin(final Canvas c, final Paint p, final int x, final int dir,
- final int top, final int baseline, final int bottom,
- final CharSequence text, final int start, final int end,
- final boolean first, final Layout l) {
- if (((Spanned) text).getSpanStart(this) == start) {
- Paint.Style style = p.getStyle();
- int oldColor = 0;
- oldColor = p.getColor();
- p.setColor(color);
- p.setStyle(Paint.Style.FILL);
- if (c.isHardwareAccelerated()) {
- if (sBulletPath == null) {
- sBulletPath = new Path();
- // Bullet is slightly better to avoid aliasing artifacts on mdpi devices.
- sBulletPath.addCircle(0.0f, 0.0f, radius, Path.Direction.CW);
- }
- c.save();
- c.translate(x + dir * radius, (top + bottom) / 2.0f);
- c.drawPath(sBulletPath, p);
- c.restore();
- } else {
- c.drawCircle(x + dir * radius, (top + bottom) / 2.0f, radius, p);
- }
- p.setColor(oldColor);
- p.setStyle(style);
- }
- }
- }
-
- @SuppressLint("ParcelCreator")
- static class CustomTypefaceSpan extends TypefaceSpan {
-
- private final Typeface newType;
-
- private CustomTypefaceSpan(final Typeface type) {
- super("");
- newType = type;
- }
-
- @Override
- public void updateDrawState(final TextPaint textPaint) {
- apply(textPaint, newType);
- }
-
- @Override
- public void updateMeasureState(final TextPaint paint) {
- apply(paint, newType);
- }
-
- private void apply(final Paint paint, final Typeface tf) {
- int oldStyle;
- Typeface old = paint.getTypeface();
- if (old == null) {
- oldStyle = 0;
- } else {
- oldStyle = old.getStyle();
- }
-
- int fake = oldStyle & ~tf.getStyle();
- if ((fake & Typeface.BOLD) != 0) {
- paint.setFakeBoldText(true);
- }
-
- if ((fake & Typeface.ITALIC) != 0) {
- paint.setTextSkewX(-0.25f);
- }
-
- paint.getShader();
-
- paint.setTypeface(tf);
- }
- }
-
- static class CustomImageSpan extends CustomDynamicDrawableSpan {
- private Drawable mDrawable;
- private Uri mContentUri;
- private int mResourceId;
-
- private CustomImageSpan(final Bitmap b, final int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = new BitmapDrawable(BaseApplication.context.getResources(), b);
- mDrawable.setBounds(
- 0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()
- );
- }
-
- private CustomImageSpan(final Drawable d, final int verticalAlignment) {
- super(verticalAlignment);
- mDrawable = d;
- mDrawable.setBounds(
- 0, 0, mDrawable.getIntrinsicWidth(), mDrawable.getIntrinsicHeight()
- );
- }
-
- private CustomImageSpan(final Uri uri, final int verticalAlignment) {
- super(verticalAlignment);
- mContentUri = uri;
- }
-
- private CustomImageSpan(@DrawableRes final int resourceId, final int verticalAlignment) {
- super(verticalAlignment);
- mResourceId = resourceId;
- }
-
- @Override
- public Drawable getDrawable() {
- Drawable drawable = null;
- if (mDrawable != null) {
- drawable = mDrawable;
- } else if (mContentUri != null) {
- Bitmap bitmap;
- try {
- InputStream is =
- BaseApplication.context.getContentResolver().openInputStream(mContentUri);
- bitmap = BitmapFactory.decodeStream(is);
- drawable = new BitmapDrawable(BaseApplication.context.getResources(), bitmap);
- drawable.setBounds(
- 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()
- );
- if (is != null) {
- is.close();
- }
- } catch (Exception e) {
- Log.e("sms", "Failed to loaded content " + mContentUri, e);
- }
- } else {
- try {
- drawable = ContextCompat.getDrawable(BaseApplication.context, mResourceId);
- drawable.setBounds(
- 0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight()
- );
- } catch (Exception e) {
- Log.e("sms", "Unable to find resource: " + mResourceId);
- }
- }
- return drawable;
- }
- }
-
- static abstract class CustomDynamicDrawableSpan extends ReplacementSpan {
-
- static final int ALIGN_BOTTOM = 0;
-
- static final int ALIGN_BASELINE = 1;
-
- static final int ALIGN_CENTER = 2;
-
- static final int ALIGN_TOP = 3;
-
- final int mVerticalAlignment;
-
- private CustomDynamicDrawableSpan() {
- mVerticalAlignment = ALIGN_BOTTOM;
- }
-
- private CustomDynamicDrawableSpan(final int verticalAlignment) {
- mVerticalAlignment = verticalAlignment;
- }
-
- public abstract Drawable getDrawable();
-
- @Override
- public int getSize(@NonNull final Paint paint, final CharSequence text,
- final int start, final int end, final Paint.FontMetricsInt fm) {
- Drawable d = getCachedDrawable();
- Rect rect = d.getBounds();
- if (fm != null) {
-// LogUtils.d("fm.top: " + fm.top,
-// "fm.ascent: " + fm.ascent,
-// "fm.descent: " + fm.descent,
-// "fm.bottom: " + fm.bottom,
-// "lineHeight: " + (fm.bottom - fm.top));
- int lineHeight = fm.bottom - fm.top;
- if (lineHeight < rect.height()) {
- if (mVerticalAlignment == ALIGN_TOP) {
- fm.top = fm.top;
- fm.bottom = rect.height() + fm.top;
- } else if (mVerticalAlignment == ALIGN_CENTER) {
- fm.top = -rect.height() / 2 - lineHeight / 4;
- fm.bottom = rect.height() / 2 - lineHeight / 4;
- } else {
- fm.top = -rect.height() + fm.bottom;
- fm.bottom = fm.bottom;
- }
- fm.ascent = fm.top;
- fm.descent = fm.bottom;
- }
- }
- return rect.right;
- }
-
- @Override
- public void draw(@NonNull final Canvas canvas, final CharSequence text,
- final int start, final int end, final float x,
- final int top, final int y, final int bottom, @NonNull final Paint paint) {
- Drawable d = getCachedDrawable();
- Rect rect = d.getBounds();
- canvas.save();
- float transY;
- int lineHeight = bottom - top;
-// LogUtils.d("rectHeight: " + rect.height(),
-// "lineHeight: " + (bottom - top));
- if (rect.height() < lineHeight) {
- if (mVerticalAlignment == ALIGN_TOP) {
- transY = top;
- } else if (mVerticalAlignment == ALIGN_CENTER) {
- transY = (bottom + top - rect.height()) / 2;
- } else if (mVerticalAlignment == ALIGN_BASELINE) {
- transY = y - rect.height();
- } else {
- transY = bottom - rect.height();
- }
- canvas.translate(x, transY);
- } else {
- canvas.translate(x, top);
- }
- d.draw(canvas);
- canvas.restore();
- }
-
- private Drawable getCachedDrawable() {
- WeakReference wr = mDrawableRef;
- Drawable d = null;
- if (wr != null) {
- d = wr.get();
- }
- if (d == null) {
- d = getDrawable();
- mDrawableRef = new WeakReference<>(d);
- }
- return d;
- }
-
- private WeakReference mDrawableRef;
- }
-
- static class ShaderSpan extends CharacterStyle implements UpdateAppearance {
- private Shader mShader;
-
- private ShaderSpan(final Shader shader) {
- this.mShader = shader;
- }
-
- @Override
- public void updateDrawState(final TextPaint tp) {
- tp.setShader(mShader);
- }
- }
-
- static class ShadowSpan extends CharacterStyle implements UpdateAppearance {
- private float radius;
- private float dx, dy;
- private int shadowColor;
-
- private ShadowSpan(final float radius,
- final float dx,
- final float dy,
- final int shadowColor) {
- this.radius = radius;
- this.dx = dx;
- this.dy = dy;
- this.shadowColor = shadowColor;
- }
-
- @Override
- public void updateDrawState(final TextPaint tp) {
- tp.setShadowLayer(radius, dx, dy, shadowColor);
- }
- }
-
- private static class SerializableSpannableStringBuilder extends SpannableStringBuilder
- implements Serializable {
-
- private static final long serialVersionUID = 4909567650765875771L;
- }
-}
\ No newline at end of file