引言
有些时候需要对TextView做出一些处理变换,比如
(必填或必选项)
需要在文字前面加红色标签 “*” 符号,(当然这种情况可以使用一些其他的方式,比如用两个TextView放在一起,但是如果布局中出现多个或者不同页面也有使用到,那就加大了我们的工作量,而且还会影响性能),还有一些其他的情况,比如超链接,删除线,上下角标等等,下面会提到。对于这些小小的需求,我们可以自己根据SpannableString这个类来定义自己想要的效果。
SpannableString
介绍
android.text.SpannableString
首先SannableString
类似于String,都可以储存字符串,和String一样实现了CharSequence
接口,结构如下:
(接口实现)
所以可以直接做为TextView.setText()方法的内容来设置。SpannableString可以用来显示复合文本,我们可以通过SpannableString给文本设置各种各样预期的样式。
SpannableString
重要的方法是setSpan(Object what, int start, int end, int flags)
,通过此方法设置不同的样式风格。
setSpan(Object what, int start, int end, int flags)
方法中包括四个参数:
Object what —— object类型,对应的各种Span类,下面介绍;
int start —— 开始应用Span的位置,索引从0开始;
int end —— 结束应用Span的位置,特效并不包括这个位置。比如如果这里数 为 3(即 第4个字符),第4个字符不会有任何特效;
int flags —— 是一个常量值,取值有四个,下面介绍。
int flags
四个取值分别如下:
Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
:前后都不包括,即在指定范围的前面和 后面插入新字符都不会应用新样式;
Spannable.SPAN_EXCLUSIVE_INCLUSIVE
:前面不包括,后面包括。即仅在范围字符 的后面插入新字符时会应用新样式;
Spannable.SPAN_INCLUSIVE_EXCLUSIVE
:前面包括,后面不包括。即仅在范围字符 的前面插入新字符时会应用新样式;
Spannable.SPAN_INCLUSIVE_INCLUSIVE
: 前后都会包括。
Object what
参数为android.text.style
下的一些Span
类,常见的Span类有:
AbsoluteSizeSpan(int size)
—— 设置字体大小,参数是绝对数值,相当于Word中的字体大小
RelativeSizeSpan(float proportion)
—— 设置字体大小,参数是相对于默认字体大小的倍 数,比如默认字体大小是x, 那么设置后的字体大 小就是x*proportion,这个用起来比较灵活, proportion>1就是放大(zoom in), proportion<1就 是缩小(zoom out)
ScaleXSpan(float proportion)
—— 缩放字体,与上面的类似,默认为1,设置后就是原来的乘以proportion,大于1时放大(zoon in),小于时缩小(zoom out)
BackgroundColorSpan(int color)
—— 背景着色,参数是颜色数值,可以直接使用android.graphics.Color里面定义的常量,或是用Color.rgb(int, int, int)
ForegroundColorSpan(int color)
—— 前景着色,也就是字的着色,参数与背景着色一致
TypefaceSpan(String family)
—— 字体,参数是字体的名字比如“sans", "sans-serif"等
StyleSpan(Typeface style)
—— 字体风格,比如粗体,斜体,参数是android.graphics.Typeface里面定义的常量,如Typeface.BOLD,Typeface.ITALIC等等。
StrikethroughSpan
—— 如果设置了此风格,会有一条线从中间穿过所有的字,就像被划掉一样。
简单的介绍结束了,下面就来根据不同的Span类型演示一下常见的几种:
以下代码都是在自定义
TextView
类中完成。若在Activity中实现可以用
textView.setText(spannableString)
。
字体颜色(ForegroundColorSpan
)
ForegroundColorSpan
为文本设置前景色,相当于TextView的setTextColor()。
(红色标签)下面就是这个文字的自定义TextView 代码:
public class StarTextView extends AppCompatTextView {
public StarTextView(Context context, AttributeSet attrs) {
super(context, attrs);
String origin = getText().toString();
if(origin.startsWith("*")){
SpannableString str = new SpannableString(origin);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
str.setSpan(foregroundColorSpan,0,1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setText(str);
}
}
}
如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
ForegroundColorSpan colorSpan = new ForegroundColorSpan(Color.parseColor("#0099EE"));
spannableString.setSpan(colorSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(spannableString);
背景颜色(BackgroundColorSpan
)
BackgroundColorSpan
,为文本设置背景色,相当于TextView的setBackground()。
代码实现如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.parseColor("#0099EE"));
spannableString.setSpan(backgroundColorSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(spannableString);
字体大小(RelativeSizeSpan
)
RelativeSizeSpan
,设置字体大小,相当于TextView中的setTextSize()。
实现代码如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(2.0f);
spannableString.setSpan(relativeSizeSpan, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(spannableString);
设置删除线(StrikethroughSpan
)
StrikethroughSpan
,给指定文字设置删除线,比如价格等。
实现代码如下:
SpannableString spannableString = new SpannableString("$588$788");
StrikethroughSpan strikethroughSpan = new StrikethroughSpan();
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(2.0f);
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
spannableString.setSpan(strikethroughSpan, 4, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(relativeSizeSpan, 0, 4, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(foregroundColorSpan, 0, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setText(spannableString);
设置下滑线(UnderlineSpan
)
UnderlineSpan
,给指定文字设置下滑线。
实现代码如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
UnderlineSpan underlineSpan = new UnderlineSpan();
spannableString.setSpan(underlineSpan, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(spannableString);
给文字设置上下标(SuperscriptSpan
)
SuperscriptSpan
,给指定文字设置上下角标。
实现代码如下:
SpannableString spannableString = new SpannableString("X2+Y2=Z2");
SuperscriptSpan superscriptSpan = new SuperscriptSpan(); //上标
SuperscriptSpan superscriptSpan1 = new SuperscriptSpan(); //上标
spannableString.setSpan(superscriptSpan, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(superscriptSpan1, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
SubscriptSpan subscriptSpan = new SubscriptSpan(); //下标
spannableString.setSpan(subscriptSpan, 7, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
RelativeSizeSpan relativeSizeSpan = new RelativeSizeSpan(0.5f);
RelativeSizeSpan relativeSizeSpan1 = new RelativeSizeSpan(0.5f);
RelativeSizeSpan relativeSizeSpan2 = new RelativeSizeSpan(0.5f);
spannableString.setSpan(relativeSizeSpan, 1, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(relativeSizeSpan1, 4, 5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(relativeSizeSpan2, 7, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
setText(spannableString);
给文字设置粗体斜体(StyleSpan
)
StyleSpan
,为文字设置风格(粗体、斜体),相当于TextView属性textStyle。
实现代码如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
StyleSpan styleSpan_B = new StyleSpan(Typeface.BOLD);
StyleSpan styleSpan_I = new StyleSpan(Typeface.ITALIC);
spannableString.setSpan(styleSpan_B, 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString.setSpan(styleSpan_I, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setHighlightColor(Color.parseColor("#36969696"));
setText(spannableString);
文字中添加图片(ImageSpan
)
ImageSpan
在文字中添加图片。可实现drawLeft
,drawRight
实现不了的功能。
实现代码如下:
SpannableString spannableString = new SpannableString("在文本中添加图片(图)");
Drawable drawable = getResources().getDrawable(R.mipmap.img_up_img);
drawable.setBounds(0, 0, 80, 80);
ImageSpan imageSpan = new ImageSpan(drawable);
spannableString.setSpan(imageSpan, 6, 8, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setText(spannableString);
文本点击事件(ClickableSpan
)
ClickableSpan
,设置可点击的文本,设置这个属性的文本可以相应用户点击事件,至于点击事件用户可以自定义,就像效果图显示一样,用户可以实现点击跳转页面的效果。如下,点击“欢欢”,跳转到另一页。
实现代码如下:
SpannableString spannableString = new SpannableString("她的名字叫欢欢");
MyClickableSpan relativeSizeSpan = new MyClickableSpan();
spannableString.setSpan(relativeSizeSpan, 5, 7, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setMovementMethod(LinkMovementMethod.getInstance());
setHighlightColor(Color.parseColor("#36969696"));
setText(spannableString);
//自定义的Clickable类,实现自己想要的效果,也可以传值等。
class MyClickableSpan extends ClickableSpan{
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
ds.setUnderlineText(false);
}
@Override
public void onClick(View widget) {
Intent intent = new Intent(getContext(), MainActivity.class);
getContext().startActivity(intent);
}
}
其中自定义Clickable
类实现了updateDrawState()
方法
ds.setUnderlineText(false);
是否显示下滑线,默认为TRUE,设置FALSE不显示。
注意:
使用ClickableSpan
的文本如果想真正实现点击的作用,必须为TextView设置setMovementMethod
方法,否则没有点击相应,至于setHighlightColor
方法则是控制点击后的背景色。
文本超链接(URLSpan
)
URLSpan
,其实上面的Clickable
就可以实现超链接的效果,URLSpan
源码中也是重写了onClick()
方法,用系统自带的浏览器打开的。
实现代码如下:
SpannableString spannableString = new SpannableString("不知道的话百度一下");
URLSpan urlSpan = new URLSpan("http://www.baidu.com");
spannableString.setSpan(urlSpan, 5, spannableString.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
setMovementMethod(LinkMovementMethod.getInstance());
setHighlightColor(Color.parseColor("#36969696"));
setText(spannableString);
其中URLSpan的onClick源码如下:
@Override
public void onClick(View widget) {
Uri uri = Uri.parse(getURL());
Context context = widget.getContext();
Intent intent = new Intent(Intent.ACTION_VIEW, uri);
intent.putExtra(Browser.EXTRA_APPLICATION_ID, context.getPackageName());
try {
context.startActivity(intent);
} catch (ActivityNotFoundException e) {
Log.w("URLSpan", "Actvity was not found for intent, " + intent.toString());
}
}
此外,还有MaskFilterSpan
可以实现模糊和浮雕效果,RasterizerSpan
可以实现光栅效果,自己可以去试一下。
然后,还可以去研究一下SpannableStringBuilder
。这里就不再多说了,该回去了。