一、TvUtils 工具类,主要帮助实现富文本相关功能
public class TvUtils {
/**
* 富文本设置字体大小
*
* @param srcString
* @param tartgetString
* @param txtSize
* @return
*/
public static SpannableString setTextPartTextSize(String srcString, String tartgetString, int txtSize) {
int position = srcString.indexOf(tartgetString);
SpannableString mSp = new SpannableString(srcString);
if (position >= 0) {
mSp.setSpan(new AbsoluteSizeSpan(txtSize, false), position, position + tartgetString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return mSp;
}
/**富文本设置字体颜色和大小
* @param srcString
* @param tartgetString
* @param targetColor
* @param txtSizeDp
* @return
*/
public static SpannableString setTextPartTextSize(String srcString, String tartgetString, int targetColor, int txtSizeDp) {
int position = srcString.indexOf(tartgetString);
SpannableString mSp = new SpannableString(srcString);
if (position >= 0) {
mSp.setSpan(new AbsoluteSizeSpan(txtSizeDp, true), position, position + tartgetString.length(),
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mSp.setSpan(new ForegroundColorSpan(targetColor), position, position + tartgetString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return mSp;
}
/**富文本设置部分文字颜色
* @param srcString
* @param tartgetString
* @param targetColor
* @return
*/
public static SpannableString setTextPartColor(String srcString,String tartgetString,int targetColor){
int position = srcString.indexOf(tartgetString);
SpannableString mSp = new SpannableString(srcString);
if (position >= 0) {
mSp.setSpan(new ForegroundColorSpan(targetColor), position, position + tartgetString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return mSp;
}
/**富文本设置部分文字背景色
* @param srcString
* @param tartgetString
* @param targetColor
* @return
*/
public static SpannableString setTextPartBg(String srcString,String tartgetString,int targetColor){
int position = srcString.indexOf(tartgetString);
SpannableString mSp = new SpannableString(srcString);
if (position >= 0) {
mSp.setSpan(new BackgroundColorSpan(targetColor), position, position + tartgetString.length(),
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
}
return mSp;
}
/**设置中划线
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setStrikethrough(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
spannableString.setSpan(strikethroughSpan, start,end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
/**设置下划线
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setUnderline(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
UnderlineSpan underlineSpan = new UnderlineSpan();
spannableString.setSpan(underlineSpan, start,end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
/**同时设置下划线和中划线
* @param src
* @param up
* @param down
* @return
*/
public static SpannableString setUpDownLine(String src,String up,String down){
int uPosition = src.indexOf(up);
int dPosition = src.indexOf(down);
SpannableString mSp = new SpannableString(src);
UnderlineSpan underlineSpan = new UnderlineSpan();
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
if (uPosition >= 0) {
mSp.setSpan(strikethroughSpan, uPosition,uPosition+up.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
if (dPosition >= 0) {
mSp.setSpan(underlineSpan, dPosition,dPosition+down.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
}
return mSp;
}
/**设置上标
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setUpScript(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
SuperscriptSpan superscriptSpan = new SuperscriptSpan();
spannableString.setSpan(superscriptSpan, start,end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
/**设置下标
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setDownScript(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
SubscriptSpan subscriptSpan = new SubscriptSpan();
spannableString.setSpan(subscriptSpan, start,end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
/**设置部分文字加粗
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setTextBold(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
StyleSpan styleSpan_B = new StyleSpan(Typeface.BOLD);
//StyleSpan styleSpan_I = new StyleSpan(Typeface.ITALIC);
spannableString.setSpan(styleSpan_B, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
// spannableString.setSpan(styleSpan_I, 8, 10, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
// textView.setHighlightColor(Color.parseColor("#36969696"));
// textView.setText(spannableString);
return spannableString;
}
/**设置部分文字倾斜
* @param src
* @param start
* @param end
* @return
*/
public static SpannableString setTextItalic(String src,int start,int end){
SpannableString spannableString = new SpannableString(src);
//StyleSpan styleSpan_B = new StyleSpan(Typeface.BOLD);
StyleSpan styleSpan_I = new StyleSpan(Typeface.ITALIC);
//spannableString.setSpan(styleSpan_B, start, end, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(styleSpan_I, 8, 10, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
// textView.setHighlightColor(Color.parseColor("#36969696"));
// textView.setText(spannableString);
return spannableString;
}
public static SpannableString setTextIcon(String src, int start, int end, Drawable drawable){
SpannableString spannableString = new SpannableString("在文本中添加表情(表情)");
//Drawable drawable = getResources().getDrawable(R.mipmap.icon_one);
drawable.setBounds(0, 0, 42, 42);
ImageSpan imageSpan = new ImageSpan(drawable);
spannableString.setSpan(imageSpan, 6, 8, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
return spannableString;
}
}
二、SpannableStringUtils,功能有重复
- 使用效果图
使用示例 ```java val create1 = SpannableStringUtils.getBuilder(“普通样式的文字,加粗”)
.setBold()
.create()
tv_textview_blod.text = create1
val create2 = SpannableStringUtils.getBuilder(“普通样式的文字,加粗倾斜”)
.setBoldItalic()
.create()
tv_textview_blodItalic.text = create2
val create3 = SpannableStringUtils.getBuilder(“普通样式的文字,下划线”)
.setUnderline()
.create()
tv_textview_three.text = create3
val create4 = SpannableStringUtils.getBuilder(“普通样式的文字,设置标识”)
.setFlag(SPAN_INCLUSIVE_EXCLUSIVE)
.create()
tv_textview_4.text = create4
val create5 = SpannableStringUtils.getBuilder(“普通样式的文字,设置foregroundcolor”)
.setForegroundColor(ContextCompat.getColor(this,R.color.red))
.create()
tv_textview_5.text = create5
val create6 = SpannableStringUtils.getBuilder(“普通样式的文字,设置backgroundcolor”)
.setBackgroundColor(ContextCompat.getColor(this,R.color.red))
.create()
tv_textview_6.text = create6
val create7 = SpannableStringUtils.getBuilder(“普通样式的文字,设置引用线颜色”)
.setQuoteColor(ContextCompat.getColor(this,R.color.red))
.create()
tv_textview_7.text = create7
val create8 = SpannableStringUtils.getBuilder(“普通样式的文字,设置列表标记”)
.setBullet(20,ContextCompat.getColor(this,R.color.red))
.create()
tv_textview_8.text = create8
val create9 = SpannableStringUtils.getBuilder(“普通样式的文字,设置字体比例”)
.setProportion(2f)
.create()
tv_textview_9.text = create9
val create10 = SpannableStringUtils.getBuilder(“普通样式的文字,设置字体横向比例”)
.setXProportion(2f)
.create()
tv_textview_10.text = create10
val create11 = SpannableStringUtils.getBuilder(“普通样式的文字,设置删除线”)
.setStrikethrough()
.create()
tv_textview_11.text = create11
val create12 = SpannableStringUtils.getBuilder(“普通样式的文字,设置上标”)
.setSuperscript()
.create()
tv_textview_12.text = create12
val create13 = SpannableStringUtils.getBuilder(“普通样式的文字,设置下标”)
.setSuperscript()
.create()
tv_textview_13.text = create13
//设置了图片以后就没有文字了 val create14 = SpannableStringUtils.getBuilder(“普通样式的文字,设置图片”)
.setResourceId(R.mipmap.ic_launcher)
.create()
//tv_textview_14.text = create14
//没什么效果,可能用法不对 tv_textview_15.movementMethod = LinkMovementMethod.getInstance() val create15 = SpannableStringUtils.getBuilder(“普通样式的文字,设置点击”)
.setClickSpan(object :ClickableSpan(){
override fun onClick(widget: View) {
Toast.makeText(this@TextViewActivity, "hello", Toast.LENGTH_SHORT).show()
}
})
.create()
tv_textview_15.text = create15
val create16 = SpannableStringUtils.getBuilder(“普通样式的文字,设置超链接”)
.setForegroundColor(ContextCompat.getColor(this,R.color.red))
.setUrl("https://www.baidu.com")
.create()
tv_textview_16.movementMethod = LinkMovementMethod.getInstance() tv_textview_16.text = create16 tv_textview_16.setTextColor(ContextCompat.getColor(this,R.color.red)) // tv_textview_16.setOnClickListener { // Toast.makeText(this@TextViewActivity, “hello”, Toast.LENGTH_SHORT).show() // }
- 3. 工具类
```java
public class SpannableStringUtils {
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 Layout.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 BlurMaskFilter.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>
* Alignment#ALIGN_NORMAL}正常</li>
* Alignment#ALIGN_OPPOSITE}相反</li>
* Alignment#ALIGN_CENTER}居中</li>
* </ul>
* @return {@link Builder}
*/
public Builder setAlign(@Nullable Layout.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>
* Blur # NORMAL}</li>
* Blur #SOLID}</li>
* Blur #OUTER}</li>
* Blur #INNER}</li>
* </ul>
* @return {@link Builder}
*/
public Builder setBlur(float radius, BlurMaskFilter.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.INSTANCE.getContext(), 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.INSTANCE.getContext(), uri), start, end, flag);
uri = null;
imageIsUri = false;
} else {
mBuilder.setSpan(new ImageSpan(Utils.INSTANCE.getContext(), 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;
}
}
}