原文:android - SpannableString或SpannableStringBuilder以及string.xml文件中的整型和string型代替

背景介绍

在开发应用过程中经常会遇到显示一些不同的字体风格的信息犹如默认的LockScreen上面的时间和充电信息。对于类似的情况,可能第一反应就是用不同的多个TextView来实现,对于每个TextView设置不同的字体风格以满足需求。

这里推荐的做法是使用android.text.*;和 android.text.style.*;下面的组件来实现RichText:也即在同一个TextView中设置不同的字体风格。对于某些应用,比如文本编辑,记事本,彩信,短信等地方,还必须使用这些组件才能达到想到的显示效果。

主要的基本工具类有android.text.Spanned; android.text.SpannableString; android.text.SpannableStringBuilder;使用这些类来代替常规String。SpannableString和 SpannableStringBuilder可以用来设置不同的Span,这些Span便是用于实现Rich Text,比如粗体,斜体,前景色,背景色,字体大小,字体风格等等,android.text.style.*中定义了很多的Span类型可供使用。

这是相关的API的Class General Hierarchy:

因为Spannable等最终都实现了CharSequence接口,所以可以直接把SpannableString和SpannableStringBuilder通过TextView.setText()设置给TextView。

使用方法

当要显示Rich Text信息的时候,可以使用创建一个SpannableString或SpannableStringBuilder,它们的区别在于 SpannableString像一个String一样,构造对象的时候传入一个String,之后再无法更改String的内容,也无法拼接多个 SpannableString;而SpannableStringBuilder则更像是StringBuilder,它可以通过其append()方法来拼接多个String:

SpannableString word = new SpannableString("The quick fox jumps over the lazy dog");SpannableStringBuilder multiWord = new SpannableStringBuilder();
multiWord.append("The Quick Fox");
multiWord.append("jumps over");
multiWord.append("the lazy dog");

创建完Spannable对象后,就可以为它们设置Span来实现想要的Rich Text了,常见的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----如果设置了此风格,会有一条线从中间穿过所有的字,就像被划掉一样

对于这些Sytle span在使用的时候通常只传上面所说明的构造参数即可,不需要设置其他的属性,如果需要的话,也可以对它们设置其他的属性,详情可以参见文档。
SpannableString和SpannableStringBuilder都有一个设置上述Span的方法:

/*** Set the style span to Spannable, such as SpannableString or SpannableStringBuilder* @param what --- the style span, such as StyleSpan* @param start --- the starting index of characters to which the style span to apply* @param end --- the ending index of characters to which the style span to apply* @param flags --- the flag specified to control*/
setSpan(Object what, int start, int end, int flags);

其中参数what是要设置的Style span,start和end则是标识String中Span的起始位置,而 flags是用于控制行为的,通常设置为0或Spanned中定义的常量,常用的有:

  • Spanned.SPAN_EXCLUSIVE_EXCLUSIVE --- 不包含两端start和end所在的端点
  • Spanned.SPAN_EXCLUSIVE_INCLUSIVE --- 不包含端start,但包含end所在的端点
  • Spanned.SPAN_INCLUSIVE_EXCLUSIVE --- 包含两端start,但不包含end所在的端点
  • Spanned.SPAN_INCLUSIVE_INCLUSIVE--- 包含两端start和end所在的端点

这里理解起来就好像数学中定义区间,开区间还是闭区间一样的。还有许多其他的Flag,可以参考这里。这里要重点说明下关于参数0,有很多时候,如果设置了上述的参数,那么Span会从start应用到Text结尾,而不是在start和end二者之间,这个时候就需要使用Flag 0。

Linkify

另外,也可以对通过TextView.setAutoLink(int)设置其Linkify属性,其用处在于,TextView会自动检查其内容,会识别出phone number, web address or email address,并标识为超链接,可点击,点击后便跳转到相应的应用,如Dialer,Browser或Email。Linkify有几个常用选项,更多的请参考文档:

  • Linkify.EMAIL_ADDRESS -- 仅识别出TextView中的Email在址,标识为超链接,点击后会跳到Email,发送邮件给此地址
  • Linkify.PHONE_NUMBERS -- 仅识别出TextView中的电话号码,标识为超链接,点击后会跳到Dialer,Call这个号码
  • Linkify.WEB_URLS-- 仅识别出TextView中的网址,标识为超链接,点击后会跳到Browser打开此URL
  • Linkify.ALL -- 这个选项是识别出所有系统所支持的特殊Uri,然后做相应的操作

权衡选择

个人认为软件开发中最常见的问题不是某个技巧怎么使用的问题,而是何时该使用何技巧的问题,因为实现同一个目标可能有N种不同的方法,就要权衡利弊,选择最合适的一个,正如常言所云,没有最好的,只有最适合的。如前面所讨论的,要想用不同的字体展现不同的信息可能的解法,除了用Style Span外还可以用多个TextView。那么就需要总结下什么时候该使用StyleSpan,什么时候该使用多个TextView:

  1. 如果显示的是多个不同类别的信息,就应该使用多个TextView,这样也方便控制和改变各自的信息,例子就是默认LockScreen上面的日期和充电信息,因为它们所承载不同的信息,所以应该使用多个TextView来分别呈现。
  2. 如果显示的是同一类信息,或者同一个信息,那么应该使用StyleSpan。比如,短信息中,要把联系人的相关信息突出显示;或是想要Highlight某些信息等。
  3. 如果要实现Rich text,没办法,只能使用Style span。
  4. 如果要实现某些特效,也可以考虑使用StyleSpan。设置不同的字体风格只是Style span的初级应用,如果深入研究,可以发现很多奇妙的功效。

实例1

<?xml version="1.0" encoding="utf-8"?>
<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"android:layout_width="wrap_content"android:layout_height="wrap_content"android:orientation="vertical"><ScrollViewandroid:layout_width="fill_parent"android:layout_height="wrap_content"><LinearLayoutandroid:layout_width="fill_parent"android:layout_height="wrap_content"android:orientation="vertical"><TextViewandroid:id="@+id/text_view_font_1"android:layout_width="fill_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/text_view_font_2"android:layout_width="fill_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/text_view_font_3"android:layout_width="fill_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/text_view_font_4"android:layout_width="fill_parent"android:layout_height="wrap_content"/><TextViewandroid:id="@+id/text_view_font_5"android:layout_width="fill_parent"android:layout_height="wrap_content"/></LinearLayout></ScrollView>
</LinearLayout>

Source code:

package com.android.effective;import java.util.regex.Matcher;import java.util.regex.Pattern;import android.app.Activity;import android.graphics.Color;import android.graphics.Typeface;import android.os.Bundle;import android.text.Spannable;import android.text.SpannableString;import android.text.SpannableStringBuilder;import android.text.style.AbsoluteSizeSpan;import android.text.style.BackgroundColorSpan;import android.text.style.ForegroundColorSpan;import android.text.style.QuoteSpan;import android.text.style.RelativeSizeSpan;import android.text.style.ScaleXSpan;import android.text.style.StrikethroughSpan;import android.text.style.StyleSpan;import android.text.style.TypefaceSpan;import android.text.style.URLSpan;import android.text.util.Linkify;import android.widget.TextView;public class TextViewFontActivity extends Activity {@Overridepublic void onCreate(Bundle bundle) {super.onCreate(bundle);setContentView(R.layout.textview_font_1);// Demonstration of basic SpannableString and spans usage
final TextView textWithString = (TextView) findViewById(R.id.text_view_font_1);String w = "The quick fox jumps over the lazy dog";int start = w.indexOf('q');int end = w.indexOf('k') + 1;Spannable word = new SpannableString(w);word.setSpan(new AbsoluteSizeSpan(22), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);word.setSpan(new StyleSpan(Typeface.BOLD), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);word.setSpan(new BackgroundColorSpan(Color.RED), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);textWithString.setText(word);// Demonstration of basic SpannableStringBuilder and spans usage
final TextView textWithBuilder = (TextView) findViewById(R.id.text_view_font_2);SpannableStringBuilder word2 = new SpannableStringBuilder();final String one = "Freedom is nothing but a chance to be better!";final String two = "The quick fox jumps over the lazy dog!";final String three = "The tree of liberty must be refreshed from time to time with " +"the blood of patroits and tyrants!";word2.append(one);start = 0;end = one.length();word2.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);word2.append(two);start = end;end += two.length();word2.setSpan(new ForegroundColorSpan(Color.CYAN), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);word2.append(three);start = end;end += three.length();word2.setSpan(new URLSpan(three), start, end, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);textWithBuilder.setText(word2);// Troubleshooting when using SpannableStringBuilder
final TextView textTroubles = (TextView) findViewById(R.id.text_view_font_3);SpannableStringBuilder word3 = new SpannableStringBuilder();start = 0;end = one.length();// Caution: must first append or set text to SpannableStringBuilder or SpannableString// then set the spans to them, otherwise, IndexOutOfBoundException is thrown when setting spans
word3.append(one);// For AbsoluteSizeSpan, the flag must be set to 0, otherwise, it will apply this span to until end of text
word3.setSpan(new AbsoluteSizeSpan(22), start, end, 0);//Spannable.SPAN_INCLUSIVE_INCLUSIVE);// For BackgroundColorSpanSpan, the flag must be set to 0, otherwise, it will apply this span to end of text
word3.setSpan(new BackgroundColorSpan(Color.DKGRAY), start, end, 0); //Spannable.SPAN_INCLUSIVE_INCLUSIVE);
word3.append(two);start = end;end += two.length();word3.setSpan(new TypefaceSpan("sans-serif"), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);// TODO: sometimes, flag must be set to 0, otherwise it will apply the span to until end of text// which MIGHT has nothing to do with specific span type.
word3.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), start, end, 0);//Spannable.SPAN_INCLUSIVE_INCLUSIVE);
word3.setSpan(new ScaleXSpan(0.618f), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);word3.setSpan(new StrikethroughSpan(), start, end, 0);//Spannable.SPAN_INCLUSIVE_INCLUSIVE);
word3.setSpan(new ForegroundColorSpan(Color.CYAN), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);word3.setSpan(new QuoteSpan(), start, end, 0); //Spannable.SPAN_INCLUSIVE_INCLUSIVE);
word3.append(three);start = end;end += three.length();word3.setSpan(new RelativeSizeSpan((float) Math.E), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);word3.setSpan(new ForegroundColorSpan(Color.BLUE), start, end, Spannable.SPAN_INCLUSIVE_INCLUSIVE);textTroubles.setText(word3);// Highlight some patterns
final String four = "The gap between the best software engineering " +"practice and the average practice is very wide¡ªperhaps wider " +" than in any other engineering discipline. A tool that disseminates " +"good practice would be important.¡ªFred Brooks";final Pattern highlight = Pattern.compile("the");final TextView textHighlight = (TextView) findViewById(R.id.text_view_font_4);SpannableString word4 = new SpannableString(four);Matcher m = highlight.matcher(word4.toString());while (m.find()) {word4.setSpan(new StyleSpan(Typeface.BOLD_ITALIC), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);word4.setSpan(new ForegroundColorSpan(Color.RED), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);word4.setSpan(new StrikethroughSpan(), m.start(), m.end(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);}textHighlight.setText(word4);// Set numbers, URLs and E-mail address to be clickable with TextView#setAutoLinkMask
final TextView textClickable = (TextView) findViewById(R.id.text_view_font_5);  final String contact = "Email: mvp@microsoft.com\n" +"Phone: +47-24885883\n" +"Fax: +47-24885883\n" +"HTTP: www.microsoft.com/mvp.asp";// Set the attribute first, then set the text. Otherwise, it won't work
textClickable.setAutoLinkMask(Linkify.ALL); // or set 'android:autoLink' in layout xml
textClickable.setText(contact);}
}

The results:

示例2

一:TextView组件改变部分文字的颜色:

TextView textView = (TextView)findViewById(R.id.textview);//方法一:
textView.setText(Html.fromHtml("<font color=\"#ff0000\">红色</font>其它颜色"));//方法二:
 String text = "获得银宝箱!";SpannableStringBuilder style=new SpannableStringBuilder(text);   style.setSpan(new BackgroundColorSpan(Color.RED),2,5,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);     //设置指定位置textview的背景颜色
  style.setSpan(new ForegroundColorSpan(Color.RED),0,2,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);     //设置指定位置文字的颜色
  textView.setText(style); 

二:android string.xml文件中的整型和string型代替:

 String text = String.format(getResources().getString(R.string.baoxiang), 2,18,"银宝箱");

对应的string.xml文件参数:

<string name="baoxiang">您今天打了%1$d局,还差%2$d局可获得%3$s!</string>

%1$d表达的意思是整个name=”baoxiang”字符串中,第一个整型

在项目开发者,经常需要把以上两者结合起来使用。可以避免很多textview的拼接,如下所示:

TextView textView = (TextView)findViewById(R.id.testview);String text = String.format(getResources().getString(R.string.baoxiang), 2,18,"银宝箱");int index[] = new int[3];index[0] = text.indexOf("2");index[1] = text.indexOf("18");index[2] = text.indexOf("银宝箱");SpannableStringBuilder style=new SpannableStringBuilder(text);   style.setSpan(new ForegroundColorSpan(Color.RED),index[0],index[0]+1,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);    style.setSpan(new ForegroundColorSpan(Color.RED),index[1],index[1]+2,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);    style.setSpan(new BackgroundColorSpan(Color.RED),index[2],index[2]+3,Spannable.SPAN_EXCLUSIVE_INCLUSIVE);    textView.setText(style);

Android利用SpannableStringBuilder设置TextView中部分文字的颜色...相关推荐

  1. Android之如何设置TextView中不同字段的字体颜色

    在这里先看看效果图: OK,有时候,在我们的项目中会要求TextView中文本有一部分的字体颜色不一样,这时我们应该使用 SpannableStringBuilder这个工具类,当然这个类的功能很强大 ...

  2. 一起学android之怎样设置TextView中不同字段的字体颜色(22)

    在这里先看看效果图: OK,有时候,在我们的项目中会要求TextView中文本有一部分的字体颜色不一样.这时我们应该使用 SpannableStringBuilder这个工具类,当然这个类的功能非常强 ...

  3. 【转】android-修改TextView中部分文字的颜色

    textView = (TextView) findViewById(R.id.textview);SpannableStringBuilder builder = new SpannableStri ...

  4. android 通过html设置textview的内容不同种颜色

    代码: String secondInfo = "<font color=\"#B7B7B7\">" + "空余位: " + & ...

  5. 设置TextView中超链接字体颜色、下划线

    ClickableSpan:这是超链接相关的样式控制和点击事件的控制类,我们需要对它进行继承,然后修改成我们需要的样式.其中,可以对超链接文本字符进行颜色.字体大小.字体.下划线.点击事件的自定义控制 ...

  6. Android之在TextView里面部分文字变颜色并且可以点击

    1.问题 在TextView里面部分文字变颜色并且可以点击 2.借助SpannableString SpannableString和String一样,是一种字符串类型 public void setS ...

  7. 在markdown中控制文字的颜色,背景色,字体大小,字体样式及颜色RGB转换工具链接

    文章目录 1. 在markdown中控制文字的颜色: 2. 在markdown中控制文字的背景色 3. 在markdown中控制文字的字体大小 4. 在markdown中控制文字的字体样式 5. 另一 ...

  8. android textview改变部分文字的颜色和string.xml中文字的替换及部分内容设置颜色、字体、超链接、图片...

    一:TextView组件改变部分文字的颜色: 1.TextView textView = (TextView)findViewById(R.id.textview); 2. 3.//方法一: 4.te ...

  9. Android TextView中的文字通过SpannableString,设置不同的颜色,字体,不同文字段的点击事件

    SpannableString其实和String一样,都是一种字符串类型,SpannableString可以直接作为TextView的显示文本,不同的是SpannableString可以通过使用其方法 ...

最新文章

  1. C 多线程编程之在类中使用多线程(thread)的方法
  2. 20秋PHP作业3,北语20秋《PHP》作业3【标准答案】
  3. 学子随感——遇见长郡浏阳(3)
  4. python离线安装包_Python2.7如何离线安装包
  5. django 403 错误:CSRF token missing or incorrect
  6. 实现多个下拉框同一批option,选中其一其他框里去除选中的项(不可选择已选过的项)--js
  7. git pull rebase
  8. Pandas GroupBy 分组(分割-应用-组合)
  9. [论文翻译]Learning Phrase Representations using RNN Encoder–Decoder for Statistical Machine Translation
  10. Flutter开发:在Flutter Plugin中引入aar——本地maven法
  11. 车辆跟踪设备中晶振分类简介
  12. C语言show用法,show的用法和例句
  13. 智慧医疗整体解决方案
  14. mysql-bin.index_mysqlbin.index是什么文件
  15. python订餐系统_用python编写的公司订餐系统的审核脚本
  16. 【贪心算法】Wooden Sticks(资源调度问题)
  17. linux firmware 框架,学习整理:arm-trusted-firmware
  18. 蓝桥杯 2016-9 取球博弈
  19. paddle 标注_一看就会,手把手教你编程,批量文章标注拼音(附源码)
  20. ssm毕设项目校园排球联赛管理系统y513u(java+VUE+Mybatis+Maven+Mysql+sprnig)

热门文章

  1. 获取比Administrator还高的权限——SYSTEM权限
  2. kubernetes 二进制安装(v1.20.16)(四)部署 master
  3. Nolan最新版本2.4 Windows和docker安装升级教程, 登陆修复.排除个别需要实名的账号,nvjdc对接青龙面板教程
  4. 标注线段长度批量lisp_晓东CAD家园-论坛-每日插件-求批量多线段长度标注-求批量多线段长度标注插件!万分感谢!!! - Powered by Discuz!...
  5. Codeforces - Qualification Rounds
  6. 持续更新:历年硕士研究生报考人数与录取人数统计
  7. Androd Camera Yuv Jepg bmp
  8. 逻辑思维能力选择题30道
  9. 自定义拍照时 拍照界面_拍照时图片比例怎么选?比构图还要提前一步的摄影攻略要做好...
  10. Python学习 - 冯诺伊曼体系结构建模与模拟 之TOY模型机