什么,同一个文本可以设置多种样式?

不知道大家在工作中是否遇到过这种情况,明明就是一个字符串,但是设计师偏让我们显示成不同的样式,具体效果和下图类似 如果你用4个TextView去做的话,只能说可以做,但是代码被别人看到肯定要喷成翔。有人说用Html.fromHtml()方法来将文本刷成html格式,然后通过设置html样式的方式来做。这样不是不可以,首先我们不是很擅长html,其次这种方式提供的效果有限,很容易就卡壳了。这里我介绍一下用原生的动态样式字符串类SpannableStringBuilder类来实现各种各样不同的文字效果,感兴趣的同学赶快上车,一起来学习一下该如何优雅地实现这种效果吧!SpannableStringBuilder介绍SpannableStringBuilder是什么? 查看一下SpannableStringBuilder代码,它实现了CharSequence接口,这个接口就是字符串的父接口,说明它和字符串是功能类似的。可以这么认为,SpannableStringBuilder是字符串的升级版本,支持动态地设置字符串的各种各样的属性,具体可以设置哪些属性呢,下面一一道来。 这是SpannableStringBuilder的类继承: 下面是String的类继承:SpannableStringBuilder是怎么使用的? 首先初始化一个SpannableStringBuilder,然后初始化一个Span,这个Span具体是哪个对象,也就是what对象依具体情况而定。比如想设置文字颜色是传入ForegroundColorSpan,如果想插入图片就传入ImageSpan即可。初始化的span通过SpannableStringBuilder对象的setSpan方法传入,最后直接通过TextView的setText()将SpannableStringBuilder对象传入即可。注意,setSpan的第二个参数和第三个参数分别代表起始文字,以及影响到的结束文字,包括前面不包括后面文字。 void setSpan (Object what, int start, int end, int flags)SpannableStringBuilder ssb = new SpannableStringBuilder(“天王盖地虎!”);
XXSpan Span = new XXSpan();
ssb.setSpan(span,0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(ssb);复制代码Spanned.SPAN_EXCLUSIVE_EXCLUSIVE是什么? 这是flgs中的一种,flags总共包括以下四种。可能大家光看文字肯定看晕了,我这里就举个例子吧,分别让大家看一下这四种flag设置以后的效果。 假设最初的文本样式时这样的: 接下来我在追风的前后分别插入一个字,效果就很明显了,插入代码如下:mSSB.insert(0,“哼”);
mSSB.insert(3,“哈”);复制代码 Spannable.SPAN_EXCLUSIVE_EXCLUSIVE:前后都不包括(在标志位【start,end)前后添加文字,新添加的文字不会有任何设置的属性) Spannable.SPAN_EXCLUSIVE_INCLUSIVE :前面不包括,后面包括。(在标志位【start,end)前添加文字,新添加的文字不会有任何设置的属性,后边的添加的文字会带有设置的what属性)
Spannable.SPAN_INCLUSIVE_EXCLUSIVE :前面包括,后面不包括。(在标志位【start,end)后添加文字,新添加的文字不会有任何设置的属性,前边边的添加的文字会带有设置的what属性)
Spannable.SPAN_INCLUSIVE_INCLUSIVE :前后都包括。前后都不包括(在标志位【start,end)前后添加文字,新添加的文字会有设置的属性) Span是什么? Span是谷歌提供的专门用来代表字符串样式的一个抽象,可以非常完美地配合SpannableStringBuilder进行使用,就相当于是一个本身可以设置参数的高级参数吧。我们可以随便点进去一个Span,然后点击其父类,最后查看该父类的实现方式,发现总共有12个Span类型,当然它们可能还会有子类。这些个Span具体代表什么意思呢,接下来笔者会将最常用的Span一一道来。常用Span类型一览1.设置字体颜色ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.parseColor("#FF0000"));
mSSB.setSpan(foregroundColorSpan,0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码2.设置背景颜色BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.parseColor("#00FF00"));
mSSB.setSpan(backgroundColorSpan,1,2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码3.设置模糊效果MaskFilter filter=new BlurMaskFilter(4.0f,BlurMaskFilter.Blur.OUTER);
MaskFilterSpan maskFilterSpan=new MaskFilterSpan(filter);
mSSB.setSpan(maskFilterSpan,2,5,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码4.设置点击事件ClickableSpan clickableSpan = new ClickableSpan() {
@Override public void onClick(View view) {
Toast.makeText(getApplicationContext(),“点击了”,Toast.LENGTH_SHORT).show();
}};
mSSB.setSpan(clickableSpan,5,7,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
// 设置此方法后,点击事件才能生效
mTv.setMovementMethod(LinkMovementMethod.getInstance());
mTv.setText(mSSB);复制代码5.设置删除线mSSB.setSpan(new StrikethroughSpan(),7,9,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setMovementMethod(LinkMovementMethod.getInstance());
mTv.setText(mSSB);复制代码6.设置下划线UnderlineSpan underlineSpan=new UnderlineSpan();
mSSB.setSpan(underlineSpan,9,12,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码7.设置文字大小AbsoluteSizeSpan ab=new AbsoluteSizeSpan(36,true);
mSSB.setSpan(ab,12,14,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码8.指定位置插入图片Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher_round);
drawable.setBounds(0,0,100,100);
ImageSpan ab = new ImageSpan(drawable);
mSSB.setSpan(ab,15,16,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码9.上下缩放效果ScaleXSpan ab = new ScaleXSpan(3.0f);
mSSB.setSpan(ab,16,18,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码10.设置粗体斜体StyleSpan ab = new StyleSpan(Typeface.BOLD_ITALIC);
mSSB.setSpan(ab,18,22,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码11.设置上标,例如多少次方SuperscriptSpan ab=new SuperscriptSpan();
mSSB.setSpan(ab,22,23,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码12.设置下标,例如log(n)SubscriptSpan ab=new SubscriptSpan();
mSSB.setSpan(ab,23,24,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码13.设置超链接URLSpan ab = new URLSpan (“http://www.baidu.com”);
mSSB.setSpan(ab,25,27,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setMovementMethod(new LinkMovementMethod());
mTv.setText(mSSB);复制代码14.设置字体样式TextAppearanceSpan ab=new TextAppearanceSpan(this, android.R.style.TextAppearance_DeviceDefault_Large);
mSSB.setSpan(ab,24,25,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码15.设置字体TypefaceSpan ab=new TypefaceSpan (“serif”);
mSSB.setSpan(ab,27,28,Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
mTv.setText(mSSB);复制代码坑点一览坑点一 再次设置样式需要获取到原来的span 请看下图,我只是设置了少年,这3个字符的样式,但是实际上后面有一个逗号也复用了该样式。总结一下就是,前面设置过的样式,后面相同字符仍然生效! 解决方案是给后面的逗号重新设置新样式,就不会采用默认的了,如下图,我给它设置了一个新样式,新样式生效了。坑点二 修改点击事件的颜色 点击事件ClickableSpan使用后,默认是有颜色的。但是它并没有提供setColor的方法,如果我们想修改它的颜色应该怎么办呢? 这里需要复写UnderlineSpan类的updateDrawState方法,在里面进行修改mSSB.setSpan(new UnderlineSpan() {
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(Color.BLUE);//设置颜色
//ds.setUnderlineText(false);//去掉下划线
}}, 5, 7, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);复制代码坑点三 插入图片时会覆盖原内容 这是默认的效果,在插入图片时,图片是会占位置的,这里王字就被图片覆盖了。 为了解决这个问题,可以在需要插入图片的地方插入几个空格,或者回车即可,让图片去覆盖不重要的字符。总结 SpannableStringBuilder是一个高度定制化的StringBuilder,可以动态修改一个字符串中间某一段的样式,功能非常强大。本文简单介绍了SpannableStringBuilder的作用,已经如何使用,其次列举出了所有可设置的Span,以后碰到有一个TextView里多样式的情况可以直接拿过去使用了。掌握了SpannableStringBuilder以后,其实还可以做很多的事情,比如加入一些动画可以制作一些很酷炫的文字效果。除此之外,还可以实现最最简单的图文混排,当然复杂的图文混排还是要自定义view去做了。当然还有很多,比如文本最后的全文、展开效果等等。
https://www.jianshu.com/p/e00f7ebc5a8c
https://www.jianshu.com/p/2d3124f51a3d
https://www.jianshu.com/p/e2953bb0b576
https://www.jianshu.com/p/80c6a4f5436a
https://www.jianshu.com/p/e19641efc173

发布了62 篇原创文章 · 获赞 0 · 访问量 5719

猜你喜欢

转载自blog.csdn.net/chunzhenwang/article/details/103374572