1 TextView和EditText灵活设置文字格式
TextView和EditText都可以设置纯文本的字符串,但是当一个字符串中需要设置不同的文字格式或者插入图片时,我们不可能去设置多个TextView+ImageView来实现,那样要累死了。(话说,刚开始我就是动态添加四个TextView来实现一个效果,好囧)。我们知道,方法setText(CharSequence text)中接收的是CharSequence。而SpannableString和SpannableStringBuilder是其实现类,是可以直接赋值的,并且,两者的setSpan()方法可以设置一些格式对象(例如字体大小,下划线,替换为图片,等),这就可以实现富文本了。
接口 Spannable--->Spanned--->CharSequence
实现子类:
|--Editable
|--SpannableString
|--SpannableStringBuilder(-->Editale)
Spannable中定义了抽象方法:setSpan(Object what, int start, int end, int flags)和removeSpan(Object what)。这两个方法实现了对字符串的灵活编辑。
实现效果如下:
2 各Span的简单应用
以下是一些常用到的一些Span
|-- ForegroundColorSpan
|-- BackgroundColorSpan
|-- StyleSpan
|-- TypefaceSpan
|-- ImageSpan
|-- URLSpan
|-- UnderlineSpan
|-- StrikethroughSpan(删除线)
具体没啥说的,直接看代码
private void setSpan() {
SpannableString spannableString = new SpannableString("君不见黄河之水天上来,");
SpannableString spannableString2 = new SpannableString("奔流到海不复回。");
SpannableString spannableString3 = new SpannableString("君不见高堂明镜悲白发,");
SpannableString spannableString4 = new SpannableString("朝如青丝暮成雪。");
SpannableString spannableString5 = new SpannableString("人生得意须尽欢。");
SpannableString spannableString6 = new SpannableString("莫使金樽空对月。");
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.GREEN);
BackgroundColorSpan backgroundColorSpan = new BackgroundColorSpan(Color.CYAN);// 同ForegroundColorSpan应用一样
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(32,true);// 32dp
UnderlineSpan underlineSpan = new UnderlineSpan();
// 文本字体格式,加粗,倾斜
StyleSpan styleSpan = new StyleSpan(Typeface.BOLD_ITALIC);
// 这四种flags的显示效果是一样的,包前不包后
spannableString.setSpan(foregroundColorSpan,1,5, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
spannableString.setSpan(styleSpan, 1, 5, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString2.setSpan(underlineSpan, 1, 5, Spanned.SPAN_EXCLUSIVE_INCLUSIVE);
spannableString3.setSpan(absoluteSizeSpan, 1, 5, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
spannableString4.setSpan(backgroundColorSpan, 1, 5, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
ImageSpan imageSpan = new ImageSpan(this,R.mipmap.iv_lyf);
spannableString5.setSpan(imageSpan, 1, 4, Spanned.SPAN_COMPOSING);
Drawable drawable = getResources().getDrawable(R.mipmap.iv_lyf);
drawable.setBounds(0, 0, drawable.getIntrinsicWidth()/3, drawable.getIntrinsicHeight()/3);//缩小为1/3
ImageSpan imageSpan1 = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
spannableString6.setSpan(imageSpan1,1,5,Spanned.SPAN_COMPOSING);
textView.setText(spannableString);
textView2.setText(spannableString2);
textView3.setText(spannableString3);
textView4.setText(spannableString4);
textView5.setText(spannableString5);
textView6.setText(spannableString6);
// 以上四种span对于新增加的文字有效果
// editText.setText(spannableString);// Spanned.SPAN_EXCLUSIVE_EXCLUSIVE 在span的文字前后新加文字都不会有span设置的效果
// editText.setText(spannableString2);// Spanned.SPAN_EXCLUSIVE_INCLUSIVE 在span的文字前后新加文字,前边无效果,后边会复用效果
// editText.setText(spannableString3);// Spanned.SPAN_INCLUSIVE_EXCLUSIVE 在span的文字前后新加文字,前边会复用效果,后边无效果
editText.setText(spannableString4);// Spanned.SPAN_INCLUSIVE_INCLUSIVE 在span的文字前后新加文字,前边和后边都会复用效果
}
以上是SpannableString的应用,还用一个SpannableStringBuilder,他们两个区别就是,后者可以通过append()方法动态添加文本。其他用法相同。如下:
private void setSpan2() {
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("天生我材必有用,");
ForegroundColorSpan foregroundColorSpan = new ForegroundColorSpan(Color.RED);
StrikethroughSpan strikethroughSpan =new StrikethroughSpan();
spannableStringBuilder.setSpan(foregroundColorSpan,0,3,Spanned.SPAN_COMPOSING);
spannableStringBuilder.append("千金散尽还复来。");
spannableStringBuilder.setSpan(strikethroughSpan,3,12,Spanned.SPAN_COMPOSING);
textView7.setText(spannableStringBuilder);
}
3 利用ClickableSpan实现可点击文本
模拟点赞人的联系显示,且可点击。
private void setMoreLikers(){
// 构造多个超链接的html, 通过选中的位置来获取用户名
StringBuilder sbBuilder = new StringBuilder();
for (int i = 0; i < 15; i++) {
sbBuilder.append("liker" + i + "、");
}
String likers = sbBuilder.substring(0, sbBuilder.lastIndexOf("、")).toString();
textView8.setMovementMethod(LinkMovementMethod.getInstance());//
textView8.setText(addClickablePart(likers), TextView.BufferType.SPANNABLE);
}
/**
* ClickableSpan 可点击的文本
* @param str
* @return
*/
private SpannableStringBuilder addClickablePart(String str) {
Drawable drawable = getResources().getDrawable(R.mipmap.ic_like);
drawable.setBounds(0,0,30,30);// 设置大小
// 赞的图标
ImageSpan span = new ImageSpan(drawable, DynamicDrawableSpan.ALIGN_BASELINE);
SpannableString spanStr = new SpannableString("l");// 被替换的
spanStr.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
// 将赞的图标和赞的人名拼接
SpannableStringBuilder ssb = new SpannableStringBuilder(spanStr);
ssb.append(str) ;
String[] likers = str.split("、");
if (likers.length > 0) {
for (int i = 0; i < likers.length; i++) {
final String name = likers[i];
final int start = str.indexOf(name) + spanStr.length();
ssb.setSpan(new ClickableSpan() {
@Override
public void onClick(View widget) {
Toast.makeText(MainActivity.this, name, Toast.LENGTH_SHORT).show();
}
@Override
public void updateDrawState(TextPaint ds) {
super.updateDrawState(ds);
// 设置文本颜色
ds.setColor(Color.RED);
// 去掉下划线
ds.setUnderlineText(false);
ds.setTextSize(30.0f);
}
}, start, start + name.length(), Spanned.SPAN_COMPOSING);
}
}
return ssb.append("赞了您.");
}
4 URLSpan用法
URLSpan urlSpan = new URLSpan("tel:10086");
URLSpan默认都设置了ClickableSpan,都是可点击的。
"tel:":电话
"mailto:":邮件
"http:":网址
"sms:":短信
"geo:":地图(需要fq)
/**
* 点击电话超链接,拨打电话
*
*/
private void setUrlSpan(){
SpannableString spannableString = new SpannableString("电话");
final URLSpan urlSpan = new URLSpan("tel:10086");
spannableString.setSpan(urlSpan, 0, 2, Spanned.SPAN_COMPOSING);
textView9.setMovementMethod(LinkMovementMethod.getInstance());
textView9.setText(spannableString);
}
/**
* 网址超链接 默认是可点击跳转的
*/
private void setUrlSpan2(){
SpannableString spannableString = new SpannableString("网址");
final URLSpan urlSpan2 = new URLSpan("http://www.csdn.net");
spannableString.setSpan(urlSpan2, 0, 2, Spanned.SPAN_COMPOSING);
textView10.setMovementMethod(LinkMovementMethod.getInstance());
textView10.setText(spannableString);
}