上一节介绍了一下Span
,有些乱,这一节我们来讲讲Android 提供的各种Span
的应用。
Span
的步骤Span
SpannableString
SpannableString
的setSpan()
方法设置span
;setSpan()
的参数会有设置文字的范围。TextView
的setText()
方法,显示SpannableString
CharacterStyle
当我们遇到在布局里无法处理的文本格式,我们就可以使用CharacterStyle
。
ClickableSpan
同时继承了CharacterStyle
和实现了UpdateAppearance
这个Span
是第一节开头提到的问题的最好解决方式。
按照上面的步骤我们来使用 ClickableSpan
实现局部点击,并且使点击的文字变色
//1.定义需要显示的文字;使“《协议》”变色,并且给“《协议》”添加点击事件,
final String protocol = "我已阅读并同意本《协议》";
//2.定义你需要的`Span`
ClickableSpan clickableSpan = new ClickableSpan() {
@Override
public void onClick(View widget) { // 在这里实现点击事件
showToast(protocol);
}
};
//3.使用将要显示文字,构造一个`SpannableString`
SpannableString spannableString = new SpannableString(protocol);
//4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
int start = protocol.length() - 4;
int end = protocol.length();
spannableString.setSpan(new CustomClickableSpan(protocol), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//5.调用`TextView`的`setText()`方法,显示`SpannableString`
mTextView.setText(spannableString);
//6.这里比平常的Span多一步,要设置一下超链接,否则不会生效
mTextView.setMovementMethod(LinkMovementMethod.getInstance());
虽然上面实现了基本的点击功能,但是美工”《协议》”这两个字的颜色是蓝色,而且不想要下划线;所以还要进一步处理,这就需要看看ClickableSpan
的内部是如何处理文字颜色了。它的源码如下:
public abstract class ClickableSpan extends CharacterStyle implements UpdateAppearance {
public abstract void onClick(View widget);
@Override
public void updateDrawState(TextPaint ds) {
ds.setColor(ds.linkColor);
ds.setUnderlineText(true);
}
}
上面的代码显示,它在updateDrawState()
方法里面,设置里字体的颜色和下划线。所以我们需要继承ClickableSpan
重写一下这个方法,在这个方法里面,设置我们希望的颜色。代码如下:
private class CustomClickableSpan extends ClickableSpan {
private String msg;
public CustomClickableSpan(String msg) {
this.msg = msg;
}
@Override
public void onClick(View widget) {
showToast(msg);
}
@Override
public void updateDrawState(TextPaint ds) {//在这里设置需要的颜色和是否需要下滑线
ds.setColor(getResources().getColor(R.color.color_blue));
ds.setUnderlineText(false);
}
}
我可以替换之前的第四步:
//4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
int start = protocol.length() - 4;
int end = protocol.length();
spannableString.setSpan(new CustomClickableSpan(protocol), start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
实现了TextView局部点击的问题,我们来说说其它的Span
。
TextView 文字的对齐方式有三种,对应的是
Layout.Alignment
中的三个枚举常量
- TextView 默认是左对齐的,对应的参数是
Layout.Alignment.ALIGN_NORMAL
- 右对齐,即跟默认相反,对应的参数是
Layout.Alignment.ALIGN_OPPOSITE
- 居中对齐的,对应的参数是
Layout.Alignment.ALIGN_CENTER
下面我们按照最开始的步骤一步一步设置Span
//1.定义需要显示的文字
String text = "Sometimes I really doubt whether there is love between my parents. " +
"Every day they are very busy trying to earn money in order to pay the high tuition for my brother and me. " +
"They don't act in the romantic ways that I read in books or I see on TV.";
//2.定义你需要的`Span`
AlignmentSpan.Standard alignmentSpan = new AlignmentSpan.Standard(Layout.Alignment.ALIGN_OPPOSITE);
//3.使用将要显示文字,构造一个`SpannableString`
SpannableString spannableString = new SpannableString(text);
//4.调用`SpannableString`的`setSpan()`方法设置`span`;`setSpan()`的参数会有设置文字的范围。
spannableString.setSpan(alignmentSpan, 0, text.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
//5.调用`TextView`的`setText()`方法,显示`SpannableString`
mTextView.setText(spannableString);
这里设置文字的对齐方式,是作用到段落上的,所以在设置 start 和 end 范围时要注意,设置几个范围的内的字符,是没有反应得。
上面代码的效果如图所示:
如果要实现居中对齐可在第2步定义Span的时候,把参数设置成
Layout.Alignment.ALIGN_CENTER
我们这里如要给TextView
的文字加上下划线,只需要重复上面的5个步骤,并且替换第2步就Ok了。
//2.定义你需要的`Span`
UnderlineSpan underlineSpan = new UnderlineSpan();
然后把它UnderlineSpan
的引用传给SpannableString
的setSpan()
方法就Ok了。
同样我只需要将定义 StrikethroughSpan
,然后将其引用传递给SpannableString
的setSpan()
方法就Ok了。
//2.定义你需要的`Span`
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
以下如果没有特殊说明,我们都是重复上面的步骤,只是修改了第二步。
//2.定义你需要的`Span`
ImageSpan imageSpan = new ImageSpan(this,R.drawable.ic_launcher);
//……省略第3步
//4.这里会把从20-30的字符替换为图片
spannableString.setSpan(imageSpan, 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
ImageSpan 还有多个构造方法,主要还有传入
Bitmap
和Drawable
。
//2.定义你需要的`Span`
SubscriptSpan span = new SubscriptSpan();
//3.使用将要显示文字,构造一个`SpannableString`
SpannableString spannableString = new SpannableString(text);
//4.将第19到第24个字符设成下标
spannableString.setSpan(span, 19, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
效果图如下:
//2.定义你需要的`Span`
SuperscriptSpan span = new SuperscriptSpan ();
//3.使用将要显示文字,构造一个`SpannableString`
SpannableString spannableString = new SpannableString(text);
//4.将第19到第24个字符设成上角标
spannableString.setSpan(span, 19, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
StyleSpan 设置的内容相当于在 布局 里设置
android:textStyle
//2.定义一个StyleSpan,并且设置 文字为粗体
StyleSpan span = new StyleSpan(Typeface.BOLD);
除了粗体,还有其它风格:
ITALIC
斜体
BOLD_ITALIC
粗斜体
TextView 默认的格式 NORMAL
参数为Android内置的文字字体家族。包含”normal”,”sans”,”serif”,”monospace”,”sans-serif-light” 等
//2.定义你需要的`Span`
TypefaceSpan span = new TypefaceSpan("serif");
style
文件里自定义文字的风格//2.定义你需要的`Span`
TextAppearanceSpan span = new TextAppearanceSpan (this,R.style.TextAppearanceSpan);
//2.这里设置的是指定范围内的文字是其他文字大小的2倍
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(2.0f);
相对的还有
AbsoluteSizeSpan
,这个指定是文字的绝对大小,参数设置的是绝对的大小//2.设置文字的绝对大小,并且设置单位为 dip AbsoluteSizeSpan span = new AbsoluteSizeSpan(24, true);
//2横向放大2倍;横向缩小应该小于 1.0f。
ScaleXSpan scaleXSpan = new ScaleXSpan(2.0f);
还剩下几个 Span
,大家可自己尝试一下,看看能出现什么效果。
另外 在这行代码中
spannableString.setSpan(imageSpan, 20, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
最后一个参数,会在获取字符长度时用到。这里用到的是 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
,表示不包含start位置的字符也不含end位置的字符。除了这个还有其他三个参数:
Spanned.SPAN_INCLUSIVE_EXCLUSIVE
(包括start,不包括end)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE
(不包括start,包括end)
Spanned.SPAN_INCLUSIVE_INCLUSIVE
(start、end 都包括)。