美文网首页
富文本工具类

富文本工具类

作者: 初见soulmate | 来源:发表于2020-10-20 15:37 被阅读0次
    
    
    import android.graphics.Bitmap;
    import android.graphics.BlurMaskFilter;
    import android.graphics.Color;
    import android.graphics.Typeface;
    import android.graphics.drawable.Drawable;
    import android.net.Uri;
    import android.text.Layout.Alignment;
    import android.text.SpannableStringBuilder;
    import android.text.Spanned;
    import android.text.TextPaint;
    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 android.view.View;
    import android.widget.TextView;
    
    import androidx.annotation.ColorInt;
    import androidx.annotation.DrawableRes;
    import androidx.annotation.NonNull;
    import androidx.annotation.Nullable;
    
    import static android.graphics.BlurMaskFilter.Blur;
    
    /**
     * @author victor
     * date 2019-08-28
     * description
     */
    public class SpannableStringUtils {
    
        /*-  样例
        private void initText() {
            ClickableSpan clickableSpan = new ClickableSpan() {
                @Override
                public void onClick(View widget) {
                    RxToast.showToast(mContext, "事件触发了", 500);
                }
    
                @Override
                public void updateDrawState(TextPaint ds) {
                    ds.setColor(Color.BLUE);
                    ds.setUnderlineText(false);
                }
            };
    
    
            // 响应点击事件的话必须设置以下属性
            mTvAboutSpannable.setMovementMethod(LinkMovementMethod.getInstance());
    
            RxTextUtils.getBuilder("").setBold().setAlign(Layout.Alignment.ALIGN_CENTER)
                    .append("测试").append("Url\n").setUrl(URL_VONTOOLS)
                    .append("列表项\n").setBullet(60, getResources().getColor(R.color.baby_blue))
                    .append("  测试引用\n").setQuoteColor(getResources().getColor(R.color.baby_blue))
                    .append("首行缩进\n").setLeadingMargin(30, 50)
                    .append("测试").append("上标").setSuperscript().append("下标\n").setSubscript()
                    .append("测试").append("点击事件\n").setClickSpan(clickableSpan)
                    .append("测试").append("serif 字体\n").setFontFamily("serif")
                    .append("测试").append("图片\n").setResourceId(R.drawable.logo)
                    .append("测试").append("前景色").setForegroundColor(Color.GREEN).append("背景色\n").setBackgroundColor(getResources().getColor(R.color.baby_blue))
                    .append("测试").append("删除线").setStrikethrough().append("下划线\n").setUnderline()
                    .append("测试").append("sans-serif 字体\n").setFontFamily("sans-serif")
                    .append("测试").append("2倍字体\n").setProportion(2)
                    .append("测试").append("monospace字体\n").setFontFamily("monospace")
                    .append("测试").append("普通模糊效果字体\n").setBlur(3, BlurMaskFilter.Blur.NORMAL)
                    .append("测试").append(" 粗体 ").setBold().append(" 斜体 ").setItalic().append(" 粗斜体 \n").setBoldItalic()
                    .append("测试").append("横向2倍字体\n").setXProportion(2)
    
                    .append("\n测试正常对齐\n").setAlign(Layout.Alignment.ALIGN_NORMAL)
                    .append("测试居中对齐\n").setAlign(Layout.Alignment.ALIGN_CENTER)
                    .append("测试相反对齐\n").setAlign(Layout.Alignment.ALIGN_OPPOSITE)
                    .into(mTvAboutSpannable);
        }
    
        private SpannableStringUtils() {
            throw new UnsupportedOperationException("u can't instantiate me...");
        }*/
    
        /**
         * 获取建造者
         *
         * @param text 样式字符串文本
         * @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>monospace</li>
             *                   <li>serif</li>
             *                   <li>sans-serif</li>
             *                   </ul>
             * @return {@link Builder}
             */
            public Builder setFontFamily(@Nullable String fontFamily) {
                this.fontFamily = fontFamily;
                return this;
            }
    
            /**
             * 设置对齐
             *
             * @param align 对其方式
             *              <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;
            }
    
            public void into(TextView textView) {
                setSpan();
                if (textView != null) {
                    textView.setText(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(new MaskFilterSpan(new BlurMaskFilter(radius, style)), start, end, flag);
                    isBlur = false;
                }
                flag = Spanned.SPAN_EXCLUSIVE_EXCLUSIVE;
            }
    
            /**
             * 给textview设置drawable
             *
             * @param textView 显示控件
             * @param drawable 图片
             * @param type     类型1.左,2.上,3.右,4.下面
             */
            public static void setDrawable(TextView textView, Drawable drawable, int type) {
                drawable.setBounds(0, 0, drawable.getMinimumWidth(), drawable.getMinimumHeight());// 设置图片宽高
                switch (type) {
                    case 1:
                        textView.setCompoundDrawables(drawable, null, null, null);// 设置到控件中
                        break;
                    case 2:
                        textView.setCompoundDrawables(null, drawable, null, null);// 设置到控件中
                        break;
                    case 3:
                        textView.setCompoundDrawables(null, null, drawable, null);// 设置到控件中
                        break;
                    case 4:
                        textView.setCompoundDrawables(null, null, null, drawable);// 设置到控件中
                        break;
    
                }
    
            }
    
            public static ClickableSpan getClickableSpan(final String textColor) {
                //文字跨度
                ClickableSpan clickableSpan = new ClickableSpan() {
                    @Override
                    public void onClick(View widget) {
                    }
    
                    @Override
                    public void updateDrawState(TextPaint ds) {
                        ds.setColor(Color.parseColor(textColor));
                        ds.setUnderlineText(false);
                    }
                };
    
                return clickableSpan;
            }
    
        }
    }
    
    

    相关文章

      网友评论

          本文标题:富文本工具类

          本文链接:https://www.haomeiwen.com/subject/ryydmktx.html