【转】深入理解TextView实现Rich Text--在同一个TextView设置不同字体风格
深入理解TextView实现Rich Text--在同一个TextView设置不同字体风格
在开发应用过程中经常会遇到显示一些不同的字体风格的信息犹如默认的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("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的初级应用,如果深入研究,可以发现很多奇妙的功效。
实例
代码如下:
encoding="utf-8"?>
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:orientation="vertical">
<ScrollView
android:layout_width="fill_parent"
android:layout_height="wrap_content">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:id="@+id/text_view_font_1"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text_view_font_2"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text_view_font_3"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text_view_font_4"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
<TextView
android:id="@+id/text_view_font_5"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
/>
</LinearLayout>
</ScrollView>
</LinearLayout>
Source code:
代码如下:
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 {
@Override
public 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:
【转】深入理解TextView实现Rich Text--在同一个TextView设置不同字体风格的更多相关文章
- 【转】(八)unity4.6Ugui中文教程文档-------概要-UGUI Rich Text
原创至上,移步请戳:(八)unity4.6Ugui中文教程文档-------概要-UGUI Rich Text 7.Rich Text UI元素和文本网格的文本可以合并多个字体样式和大小.对 UI系统 ...
- (八)unity4.6Ugui中文教程文档-------概要-UGUI Rich Text
大家好,我是孙广东. 转载请注明出处:http://write.blog.csdn.net/postedit/38922399 更全的内容请看我的游戏蛮牛地址:mod=guide&view ...
- PeopleSoft Rich Text Boxes上定制Tool Bars
在使用PT8.50或在8.51时,你可能遇到过Rich-text编辑框.该插件使你能够格式化文本,添加颜色.链接.图片等等.下面是效果图: 如果页面中只有这么一个字段,该文本框就会有足够的空间来容 ...
- selenium处理rich text(富文本框)
WordPress 的 rich text 采用js,先让selenium切换到iframe中 driver.switchTo().frame("content_ifr"); 然 ...
- Rich Text Editor for MVC
在网站开发中难免会用到富文本编辑器,本文将介绍一款富文本编辑器(在线HTML编辑器) Rich Text Editor ,简要说明一下其在MVC中的使用. 具体使用情况和下载地址请参考:http:// ...
- NicEdit - WYSIWYG Content Editor, Inline Rich Text Application
NicEdit - WYSIWYG Content Editor, Inline Rich Text Application By calling the nicEditors.allTextarea ...
- 键盘回收(text filed,textview)
键盘回收 #pragma mark - TextField 代理方法 - (BOOL)textFieldShouldReturn:(UITextField *)textField { [self.vi ...
- Selenium Webdriver——JS处理rich text(富文本框)
126邮件正文邮件的rich text 先让selenium切换到iframe中 driver.switchTo().frame(driver.findElement(By.className(&qu ...
- web & Rich Text Editor
web & Rich Text Editor 富文本编辑器 http://www.wangeditor.com/ https://github.com/wangfupeng1988/wangE ...
随机推荐
- 关于JS中作用域的销毁和不销毁的情况总结
window全局作用域->页面关掉才销毁函数执行会形成私有的作用域 1)作用域的销毁 一般情况下,函数执行形成一个私有的作用域,当执行完成后就销毁了->节省内存空间 2)作用域的不立即销毁 ...
- Struts2_ValueStack,OGNL详解
一.ValueStack 1.ValueStack是一个接口,在struts2中使用OGNL(Object-Graph Navigation Language)表达式实际上是使用实现了Value ...
- 禁止ViewState的3种解决方法
默认情况下,ViewState是被启用的,比如提交表单后,表单中输入的值会自动保留.但是如果不需要保留,也可以将其禁用,这样可以节省资源. 下面3种方式就可以分别禁用某一个控件.某一个页面和整个应 ...
- OpenCV 3.0 VS2010 Configuration
Add in the system Path: C:\opencv\build\x86\vc10\bin; Project->Project Property->Configuration ...
- OpenCV count the number of connected camera 检测连接的摄像头的数量
有时候在项目中我们需要检测当前连接在机子上的摄像头的数量,可以通过下面的代码实现,其中连接摄像头的最大数量maxCamNum可以任意修改: /** * Count current camera num ...
- thinkphp模板中foreach循环没数据的错误解决
从控制器方法中$this->assign();函数将值传递给html模板 但是模板不显示数据,直接出来的是代码,效果就和html中写了php代码不能解析一样. 原来是我将thinkphp框架的引 ...
- sql 语句大小写的问题
关键字不区分大小写 例如 select ,from, 大小写均可 标识符区分大小写 例如 表名,列名 标识符如果不加双引号,默认是按大写执行 标识符如果加双引号,则是按原始大小写执行 但是,当表名加上 ...
- 字符串&数组的相互转换
字符串 -> 数组 方法一: $str = "abcd" $s2 = $str.GetEnumerator() #$s2是无法使用下标的方式进行索引的,因为其不是array ...
- Python函数1
Python 函数命令的使用 想想我们之前数学中学到的函数,首先我们需要定义一个函数,例如f(x)=x, 当x输入任意数的时候,f(x)都能输出和x相等的数值. 那么在Python中是如何实现的呢? ...
- rsync安装及配置
一.Server端 CentOS 6下安装yum -y install xinetd1.配置:vi /etc/xinetd.d/rsyncservice rsync{ disable = yes ...