Android开发之TextView高级应用
我们平时使用TextView往往让它作为一个显示文字的容器,但TextView的功能并不局限于此。下面就和大家分享一下TextView的一些使用技巧。
Android中设置文本样式的几种方法:
1.将android:autoLink属性值设为true。系统会自动识别E-mail、电话、网址等特殊文本。
2.使用Html标签,例如,<font>、<img>等。不要设置 android:autoLink 属性。
3.在Java代码中直接使用Span对象来设置文本样式。这种方法需要将文本转换成一个SpannableString或SpannableStringBuilder对象,然后在SpannableString或SpannableStringBuilder对象中使用setSpan方法将要设置样式的文本转换成相应的Span对象。
4.在字符串资源中使用<a>标签(只支持<a>标签)设置可单击的链接,不要设置android:audoLink属性。
上面4种方法只要涉及单击动作,就必须使用TextView.setMovementMethod方法设置相应的MovementMethod对象。
1.在TextView中显示图像
我们浏览网的时候,上面的有很多图文并茂的文章,这些文章大部分都是从服务器的数据库中取出并显示在网页上的。那么如何在网页上显示图文并茂的文章呢?有过Java Web或.NET开发经验的人,会说用s:textfield或asp:label绑定。用它们是因为它们可以将<img>标签的src对应的图像地址(也是图像资源的唯一标识)直接交给浏览器出处理。这样就可以将<img/>的src对应的图片显示出来。
那么,在Android中如何用TextView显示图片呢?
在解析Html标签来方面Android系统没有浏览器那么强大,Android系统不会直接根据src属性说指向的的值自动获取并显示图片,这一切都需要我们来帮它来完成。说白了,src属性指的是什么只有开发者自己知道。开发者需要告诉系统src属性到底指的是什么,然后系统才会知道怎么做。
解析src属性值需要ImageGetter对象的getDrawable方法来完成。ImageGetter是一个接口。使用Html.fromHtml会使这一过程变得简单。(关于Html.fromHtml的介绍)
txtShow=(TextView)findViewById(R.id.txtShow); String htmlText="小黄人1号:<img src=‘xiaohuangren1‘/>" +"小黄人2号:<img src=‘xiaohuangren2‘/>"+"小黄人3号:<img src=‘xiaohuangren3‘/>"; txtShow.setText(getSpanned(htmlText)); |
/** *将Html解析成样式文本 *@return spanned Spanned * */ private Spanned getSpanned(String htmlText) { //TODO Auto-generated method stub Spanned spanned=Html.fromHtml(htmlText,new ImageGetter() { @Override public Drawable getDrawable(String source) { //TODO Auto-generated method stub //装在图像资源 Drawable drawable=getResources().getDrawable(getResourceId(source)); if (source.equals("xiaohuangren1")) { //设置图像的缩放 drawable.setBounds(0, 0, 56, 56); }elseif (source.equals("xiaohuangren2")) { //设置图像的缩放 drawable.setBounds(0, 0, 36, 36); }elseif (source.equals("xiaohuangren3")) { //设置图像缩放到原来的75% drawable.setBounds(0, 0,(int) (drawable.getIntrinsicWidth()*0.75), (int) (drawable.getIntrinsicHeight()*0.75)); } return drawable; } },null); return spanned; } /** *利用反射技术从R.drawable类中通过图像资源文件名获得相应图像资源的ID *@param name String图像资源名 *@return图像资源ID int * */ protectedint getResourceId(String name) { //TODO Auto-generated method stub try { //根据资源ID的变量名(也就是图像资源的文件名)获取Field对象 Field field=R.drawable.class.getField(name); //取得并返回资源ID的值 return Integer.parseInt(field.get(null).toString()); }catch (Exception e) { //TODO: handle exception } return 0; } |
2.单击TextView中的内容打开指定Activity
虽然TextView可以自动识别特殊文本(网址、电话号、E-mail等),并可以通过单击触发不同的动作。但是如果开发者想通过单击链接来显示指定的组件(如Activity、Service等)那么怎么来实现呢?
TextView自动识别的网址、电话号、E-mail等,都是在ClickableSpan类的onClick方法中通过Action调用相应的组件来实现的。现在我们就采用类似的方法,通过自己实现onClick方法来达到自定义自定义单击动作的目的。
/** *单击TextView中的内容启动指定组件 * */ privatevoid launchComponentByTextView() { //TODO Auto-generated method stub txtLink=(TextView)findViewById(R.id.txtLink); String str="单击我启动一个Activity"; //将文本转换成SpannableString对象 SpannableString spannableString=new SpannableString(str); //将spannableString所有文本设置成ClickableSpan对象,并实现onClick方法 spannableString.setSpan(new ClickableSpan() { @Override publicvoid onClick(View widget) { //TODO Auto-generated method stub //启动指定Activity Intent intent=new Intent(MainActivity.this, SecondActivity.class); startActivity(intent); } }, 0, str.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); txtLink.setText(spannableString); //在单击链接时凡是要执行的动作,都必须设置MovementMethod对象 txtLink.setMovementMethod(LinkMovementMethod.getInstance()); } |
实例分析:
在本例中setSpan方法的第四个参数设置成了Spanned.SPAN_EXCLUSIVE_EXCLUSIVE,该标志在 TextView 控件中意义不大,但在 EditText控件中表示在当前Span效果的前后输入字符时并不应用Span的效果。关于SpannableString的详细介绍大家可以参照:Android开发之SpannableString详解。
3.为指定文本添加颜色和背景色
从前面几个实例的内容可以得知设置字符中某个子字符串的样式(变成可单击的链接、设置字体等)需要如下几步。
(1) 将字符串转换成SpannableString或SpannableStringBuilder对象。
(2) 获得要设置样式的子字符串在原字符串中的开始位置和子字符串后面的字符的位置,也就是 start和end。
(3) 创建一个Span对象(所有android.text.style包中的XxxSpan类创建的对象的统称,Xxx表示URL、BackgroundColor等类的前缀)。
(4) 使用setSpan方法设置个Span对象,也就足说?将要设置样式的子字符串转换成坤拙对象。
(5) 用处理完的SpannableString或SpannableStringBuilder对象设置相应的控件(如TextView、EditText、Button等)。
在Android SDK的andrmd.text.styte包中提供很多现成的Span对象,例如’ BackgroundColorSpan类就是一个很常用的Span类,该类的功能是设置指定字符串的背景色,使用方法如下:
txtSetBackgroundColor=(TextView)findViewById(R.id.txtSetBackgroundColor); String str="没有背景|黄色背景"; //第一步将字符串转换成SpannableString对象 SpannableString spannableString=new SpannableString(str); //第二步确定设置要设置的子字符串在原字符串的开始位置和接收位置即start和end String subStr="黄色背景"; int start=str.indexOf(subStr); int end=start+subStr.length(); //第三步创建一个BackgroundColorSpan对象 BackgroundColorSpan backgroundColorSpan=new BackgroundColorSpan(Color.YELLOW); //第四步使用setSpan方法将指定子字符串转换成BackgroundColorSpan对象对象 spannableString.setSpan(backgroundColorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第五步用SpannableString对象设置TextView控件 txtSetBackgroundColor.setText(spannableString); |
BackgroundColorSpan只能设置文字的背景色,为了更加通用,我们来自己编写一个ColorSpan类,使其同时可以设置文字颜色和背景色(android.text.style.ForegroundColorSpan类可以设置文字颜色,但并没有可同时设置背景和文字颜色的Span类)。在实例2给出了一个通过继承ClickableSpan类来编写自定义Span类的例子,不过这个例子需要处理链接动作,所以必须要继承ClickableSpan类。而本例只要设置文字和背景颜色即可,并不需要处理任何动作,因此,只需要从CharacterStyle类继承即可。实际上,ClickableSpan也是CharacterStyle的子类。可以设置文字和背景颜色的ColorSpan类的代码如下:
/** * Describe:</br> *</br>自定义一个CharacterStyle的子类 *</br>用于修改文字的颜色和背景色 *</br>@author jph *</br>Date:2014.08.10 * */ publicclass ColorSpanextends CharacterStyle { //声明文字的颜色和背景色 privateinttextColor,backgroundColor; /** *初始化ColorSpan类 *@param textColor 文字颜色 *@param backgroundColor文字背景色 * */ public ColorSpan(int textColor,int backgroundColor) { //TODO Auto-generated constructor stub this.textColor=textColor; this.backgroundColor=backgroundColor; } //覆盖CharacterStyle类中的updateDrawState方法,并在该方法中设置字体颜色和背景色 @Override publicvoid updateDrawState(TextPaint tp) { //TODO Auto-generated method stub tp.bgColor=backgroundColor; tp.setColor(textColor); } } |
在ColorSpan类中实现了CharacterStyle类的updateDrawState方法。该方法在系统开始绘制要设置样式的字符串之前调用,以便修改绘制文字的属性,例如,文字颜色、背景颜色等。其中TextPaint是Paint的子类。Paint类用于描述绘制的属性,如画笔的颜色、画笔的粗细等。现在我们来同时使用BackgroundColorSpan和ColorSpan类设置文字和背景颜色,代码如下:
txtMyColor=(TextView)findViewById(R.id.txtMyColor); ColorSpan colorSpan=new ColorSpan(Color.RED, Color.WHITE); String str="红色字体|灰色背景"; String subStr="灰色背景"; int start=str.indexOf(subStr); int end=start+subStr.length(); SpannableString spannableString=new SpannableString(str); spannableString.setSpan(colorSpan, 0, start, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); colorSpan=new ColorSpan(Color.WHITE, Color.GRAY); spannableString.setSpan(colorSpan, start, end, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); txtMyColor.setText(spannableString); |