在上一篇博客TextView显示丰富多彩的文字(一)——如何使用CharacterStyle格式化字符中介绍了CharacterStyle的接口,并使用了Character的多个实现类介绍了一下文字改变效果。下面是Spannable的setSpan的API:
其中可以看到第一个参数不止可以是CharacterStyle,还可以使ParagraphStyle、TextWatecher和SpanWatcher的子类。今天这篇博客主要介绍如何使用ParagraphStyle。
ParagraphStyle
ParagraphStyle是一个接口,实现该接口的类会在段落级别影响文本格式化。
ParagraphStyle有很多实现类。下面是具体的层次图,查看文档可以知道,第二层的子类还都是接口,只有最底层的才是实现类。
下面我们就以例子来说明具体每个格式的用法。
示例
首先先看一下没有添加任何效果的显示。为了让下面的示例能看出设置margin的区别,特地将TextView的背景设为绿色,没有padding。
下面是代码,就是简单的获取了TextView,然后用SpannableString转换了一下文本,再设置给了TextView。
private TextView mTextView;
private String paragraph = "中新网北京9月10日电 今天," +
"连通东西部多条铁路干线的郑徐高铁将正式通车运营," +
"中国高铁网络再次得到完善,东中西部民众的高铁出行也" +
"更加便利。与此同时,今天开始,受郑徐高铁开通影响," +
"全国铁路再次迎来一次运行图大调整。";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_paragraph);
mTextView = (TextView) findViewById(R.id.paragraph_tv);
SpannableString spannableString = new SpannableString(paragraph);
mTextView.setText(spannableString);
}
LeadingMarginSpan
LeadingMarginSpan会影响段落的leading margin(我称它为领先margin)。同一个段落可以设置多个不同的leading margin。这些margin会叠加。如果段落是一个从右到左的,那么margin就会从右边开始计算。使用LeadingMarginSpan需要被添加到整个段落,即范围从第一个字符到最后一个字符。下面是实现该接口的类的例子。
LeadingMarginSpan.Standard
该类只会调整margin,而不会做任何渲染。可以用该类来实现段落的整体右移。先看该类的构造方法:
LeadingMarginSpan.Standard(int first, int rest)
LeadingMarginSpan.Standard(int every)
LeadingMarginSpan.Standard(Parcel src)
其中第三个是因为实现了Parcelable接口的缘故,暂不考虑。第一个构造方法有两个参数,其中第一个参数设置第一行的margin,第二个参数设置其余行的margin(==可以用该构造方法实现首行缩进的功能==)。第二个构造方法就是设置每一行的margin都一样。下面先看第二种构造方法的效果:
//使用每行都一样的LeadingMarginSpan.Standard
LeadingMarginSpan.Standard standard = new LeadingMarginSpan.Standard(60);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果如下,就像TextView内部设置了leftPadding一样
下面再看第一种构造方法的用法,实现首行缩进的功能。
//使用首行缩进的LeadingMarginSpan.Standard
LeadingMarginSpan.Standard standard = new LeadingMarginSpan.Standard(60,20);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果如下:
BulletSpan
废话不多说,先看代码,再看效果。看了效果就会知道这个效果是怎样的了。
//使用默认的BulletSpan
BulletSpan bulletSpan = new BulletSpan();
spannableString.setSpan(bulletSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
上面是使用默认的BulletSpan,看了效果后,可以知道BulletSpan会在段落前加上个圆点。可以用于无序列表。BulletSpan有几个构造方法,如下:
BulletSpan()
BulletSpan(int gapWidth)
BulletSpan(int gapWidth, int color)
BulletSpan(Parcel src)
其中两个参数的gapWidth用于设置圆点和文字之间的距离,一个用于设置圆点颜色。下面将通过两个参数的构造方法构造BulletSpan,效果如下:
其中设置的间隔为50,颜色为红色,代码如下:
//使用两个构造方法的BulletSpan
BulletSpan bulletSpan = new BulletSpan(50, Color.RED);
spannableString.setSpan(bulletSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
QuoteSpan
还是先看代码和效果
//使用默认的QuoteSpan
QuoteSpan quoteSpan = new QuoteSpan();
spannableString.setSpan(quoteSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
可以看到QuoteSpan的效果是在文本左边加上一条竖直的线,默认颜色为蓝色。下面尝试改变该颜色:
//使用带颜色的QuoteSpan
QuoteSpan quoteSpan = new QuoteSpan(Color.RED);
spannableString.setSpan(quoteSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果如下,竖直的线确实变成了红色
DrawableMarginSpan
DrawableMaiginSpan有两个构造方法。其中
DrawableMarginSpan(Drawable b)
DrawableMarginSpan(Drawable b, int pad)
我们这里展示第二个构造方法的的效果,其中第一个构造方法中pad参数为0。pad参数指图标和文字之间的距离。
DrawableMarginSpan drawableMarginSpan = new DrawableMarginSpan(getResources().getDrawable(R.mipmap.ic_launcher),30);
spannableString.setSpan(drawableMarginSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果如下:
IconMarginSpan
IconMarginSpan和DrawableSpan效果类似,只不过DrawableMarginSpan的构造方法中只能传入Drawable对象,而IconMarginSpan构造方法中只能传入Bitmap对象。下面是使用和效果:
//使用IconMarginSpan
IconMarginSpan iconMarginSpan = new IconMarginSpan(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher), 30);
spannableString.setSpan(iconMarginSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
IconMarginSpan和DrawableMarginSpan的共同点还在于它们不仅仅实现了LeadingMarginSpan,还实现了LineHeightSpan。
AlignmentSpan
AlignmentSpan.Standard
还是先看用法和效果:
//使用AlignmentSpan.Standard居中显示
AlignmentSpan.Standard standard = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_CENTER);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果:
//使用AlignmentSpan.Standard靠右显示
AlignmentSpan.Standard standard = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果:
//使用AlignmentSpan.Standard正常显示
AlignmentSpan.Standard standard = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_NORMAL);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果:
从上面可以看出来Alignment可以控制段落的对齐方式,就像Word中居中、靠右或靠左显示。
组合多个效果
下面使用了首行缩进的LeadingMarginSpan.Standard、BulletSpan和QuoteSpan,根据文档中会叠加这些效果。
//使用首行缩进的LeadingMarginSpan.Standard
LeadingMarginSpan.Standard standard = new LeadingMarginSpan.Standard(60,20);
spannableString.setSpan(standard, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//使用两个构造方法的BulletSpan
BulletSpan bulletSpan = new BulletSpan(50, Color.RED);
spannableString.setSpan(bulletSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
//使用带颜色的QuoteSpan
QuoteSpan quoteSpan = new QuoteSpan(Color.RED);
spannableString.setSpan(quoteSpan, 0, paragraph.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
效果如下:
从上图可以看出,有了左边padding的效果、红色圆点和竖直红线的效果。
总结
以上基本就是常用的ParagraphStyle的实现类,有一点需要注意的是,上面的例子中文字都是都是从左到右的,如果设置了从右到左,那么margin就会在右边,而Alignment的NORMAL也就是靠右显示。其中SpannableString的用法,如果不了解的话,可以在第一篇TextView显示丰富多彩的文字(一)——如何使用CharacterStyle格式化字符博客中查看。