TextView字体样式Spannable

来源:互联网 发布:python论坛源码 编辑:程序博客网 时间:2024/06/05 10:59

在android中,有时候需要对文本进行各种特别的设置,比如颜色、大小、首行缩进,或者是在一段文本中加入图片,甚至是书写一些特殊的公式。如果通过布局文件使用多个控件来实现,一方面会使的使用起来特别的复杂,增加了布局文件维护的难度,另一方面,如果加入了太多的控件,在页面加载时也要耗费更多的资源。如果在HTML中,则可以使用各种标签来实现这些特殊效果,而在android中有类似的机制,只不过不是使用标签来实现,而是使用Spannable对象来实现。

一、关于Spannable的构建:

可以看出,Spannable继承自Spanned接口,而实际上,Spanned继承自CharSequence接口:

在TextView的setText(CharSequence text)方法中,要求的参数正好是一个CharSequence对象,因此,我们可以通过Spannable对象来直接使用setText来完成文本的设置。在使用中通常使用Spannable spn = new SpannableString("字符串");或者通过SpannableStringBuilder对象来进行构建。

二、给Spannable对象设置样式:

在构建除了Spannable对象以后,就可以使用spannable.setSpan(Obj what, int start, int end, int flags)方法来进行样式的设置了,其中参数what是具体样式的实现对象,start则是该样式开始的位置,end对应的是样式结束的位置,参数flags,定义在Spannable中的常量,常用的有:

Spanned.SPAN_EXCLUSIVE_EXCLUSIVE --- 不包含两端start和end所在的端点              (a,b)
Spanned.SPAN_EXCLUSIVE_INCLUSIVE --- 不包含端start,但包含end所在的端点       (a,b]
Spanned.SPAN_INCLUSIVE_EXCLUSIVE --- 包含两端start,但不包含end所在的端点   [a,b)
Spanned.SPAN_INCLUSIVE_INCLUSIVE--- 包含两端start和end所在的端点                     [a,b]

但实际测试这其中似乎并未有差别,而在start和end相同的情况下,则只对start所在字符的当前行起作用。

三、样式分析:

用来构建样式的具体的类都在android.text.style包下,下面逐一进行分析。

1.AbsoluteSizeSpan

顾名思义,AbsoluteSizeSpan是指绝对尺寸,通过指定绝对尺寸来改变文本的字体大小。该类有三个构造函数:
AbsoluteSizeSpan(int size)、AbsoluteSizeSpan(int size, boolean dip)、AbsoluteSizeSpan(Parcel src)。
AbsoluteSizeSpan(int size):参数size, 以size的指定的像素值来设定文本大小。
AbsoluteSizeSpan(int size, boolean dip):参数size,以size的指定像素值来设定文本大小,如果参数dip为true则以size指定的dip为值来设定文本大小。
AbsoluteSizeSpan(Parcel src):参数src,包含有size和dip值的包装类。在该构造中
public AbsoluteSizeSpan(Parcel src) {
mSize = src.readInt();
mDip = src.readInt() != 0;    
}
使用范例:
Parcel p = Parcel.obtain();
p.writeInt(29);//字体大小
p.writeInt(8);//是否是dip单位
p.setDataPosition(0);
AbsoluteSizeSpan ass = new AbsoluteSizeSpan(p);
效果:

2.AlignmentSpan.Standard

AlignmentSpan.Standard,标准文本对齐样式,该类有两个构造函数,AlignmentSpan.Standard(Layout.Alignment align)和AlignmentSpan.Standard(Parcel src)。AlignmentSpan.Standard(Layout.Alignment align):参数align,Layout.Alignment类型的枚举值。包括居中、正常和相反三种情况。
AlignmentSpan.Standard(Parcel src):参数src,包含有标准字符串的Parcel类,其值应为"ALIGN_CENTER"、"ALIGN_NORMAL"或"ALIGN_OPPOSITE"中的之一,对应Layout.Alignment枚举中的三个类型。使用示例:
Parcel p = Parcel.obtain();
p.writeString(\"ALIGN_CENTER\");
p.setDataPosition(0);
AlignmentSpan.Standard standard = new AlignmentSpan.Standard(p);
效果:

3.BackgroundColorSpan

BackgroundColorSpan,背景色样式,显然可以用来设定文本的背景色。该类有两个构造函数,BackgroundColorSpan(int color)和BackgroundColorSpan(Parcel src)。
BackgroundColorSpan(int color):参数color,颜色值。
BackgroundColorSpan(Parcel src):参数src,包含颜色值信息的包装类,使用方法如下:
Parcel p = Parcel.obtain();
p.writeInt(Color.GREEN);
p.setDataPosition(0);
BackgroundColorSpan bcs = new BackgroundColorSpan(p);
效果:

4.BulletSpan

BulletSpan,着重样式,类似于HTML中的<li>标签的圆点效果。该类有4个构造函数BulletSpan()、BulletSpan(int gapWidth)、BulletSpan(int gapWidth,int color)、BulletSpan(Parcel src)。
BulletSpan():仅提供一个与文本颜色一致的符号。
BulletSpan(int gapWidth): 提供一个与文本颜色一致的符号,并指定符号与后面文字之间的空白长度。
BulletSpan(int gapWidth,int color):提供一个指定颜色的符号,并指定符号与后面文字之间的宽度。
BulletSpan(Parcel src):参数src,包含宽度、颜色信息的包装类,在以此构造时,构造函数的调用如下:
mGapWidth = src.readInt();
mWantColor = src.readInt() != 0;\nmColor = src.readInt();
如果使用Parcel作为参数时,使用方式为:
Parcel p = Parcel.obtain();
p.writeInt(20);//设置gapWidth
p.writeInt(1);//设置是否使用颜色
p.writeInt(Color.YELLOW);//设置颜色
p.setDataPosition(0);
BulletSpan bs3 = new BulletSpan(p);
效果:

5.DrawableMarginSpan

DrawableMarginSpan,图片+Margin样式,该类有两个构造函数:DrawableMarginSpan(Drawable b)、DrawableMarginSpan(Drawable b,int pad)。
DrawableMarginSpan(Drawable b):参数b,用于显示的图片。
DrawableMarginSpan(Drawable b,int pad):参数b,用于显示的图片,参数pad,图片和文字的距离。
效果:

6.ForegroundColorSpan

ForegroundColorSpan,字体颜色样式,用于改变字体颜色。该类有两个构造函数:ForegroundColorSpan(int color)、ForegroundColorSpan(Parcel src)。
ForegroundColorSpan(int color):参数color,字体颜色。
ForegroundColorSpan(Parcel src):参数src,包含字体颜色信息的包装类,使用如下:
Parcel p = Parcel.obtain();
p.writeInt(Color.YELLOW);
p.setDataPosition(0);
ForegroundColorSpan fcs = new ForegroundColorSpan(p);
效果:

7.IconMarginSpan

IconMarginSpan,图标+Margin样式,该类与DrawableMarginSpan使用上很相似。本类有两个构造函数:
IconMarginSpan(Bitmap b):参数b,用于显示图像的bitmap。
IconMarginSpan(Bitmap b,int pad):参数b,用于显示图像的bitmap,参数pad,Bitmap和文本之间的间距。
效果:

8.ImageSpan

ImageSpan,图片样式,主要用于在文本中插入图片。本类构造函数较多,但主要是针对Bitmap和Drawable的,也可以通过资源Id直接加载图片。如下:
ImageSpan(Bitmap b):.参数b,用于显示的Bitmap。该方法已过时,改用Use ImageSpan(Context, Bitmap)代替。
ImageSpan(Bitmap b, int verticalAlignment):参数b,用于显示的Bitmap,参数verticalAlignment,对齐方式,对应ImageSpan中的常量值。该方法已过时,改用ImageSpan(Context, Bitmap, int)代替。
ImageSpan(Context context, Bitmap b):参数context,传入的上下文,参数b,用于显示的Bitmap。
ImageSpan(Context context, Bitmap b, int verticalAlignment):参数context,传入的上下文,参数b,用于显示的Bitmap,参数verticalAlignment,对齐方式。
ImageSpan(Drawable d):参数d,用于显示的Drawable,此Drawable须设置大小。
ImageSpan(Drawable d, int verticalAlignment):参数d,用于显示的Drawable,参数verticalAlignment,对齐方式。
ImageSpan(Drawable d, String source):参数d,用于显示的Drawable,参数source,资源字符串。
ImageSpan(Drawable d, String source, int verticalAlignment):参数d,用于显示的Drawable,参数source,资源字符串,参数verticalAlignment,对齐方式。
ImageSpan(Context context, Uri uri):参数context,传入的上下文,参数uri,图片的uri。
ImageSpan(Context context, Uri uri, int verticalAlignment):参数context,传入的上下文,参数uri,图片的uri,参数verticalAlignment,对齐方式。
ImageSpan(Context context, int resourceId):参数context,传入的上下文,参数resourceId,图片的资源id。
ImageSpan(Context context, int resourceId, int verticalAlignment)参数context,传入的上下文,参数resourceId,图片的资源id,参数verticalAlignment,对齐方式。
效果:

9.LeadingMarginSpan

LeadingMarginSpan.Standard,文本缩进的样式。有3个构造函数,分别为:
Standard(int arg0):参数arg0,缩进的像素。
Standard(int arg0, int arg1):参数arg0,首行缩进的像素,arg1,剩余行缩进的像素。
Standard(Parcel p): 参数p,包含缩进信息的包装类。在构造时,
public Standard(Parcel src) {
    mFirst = src.readInt();\n"+
    mRest = src.readInt();\n"+
}
使用方式:
Parcel p = Parcel.obtain();
p.writeInt(20);
p.writeInt(30);
p.setDataPosition(0);
Standard lms = new Standard(p);
效果:


10.MaskFilterSpan

MaskFilterSpan,滤镜样式,只有一个构造函数:
MaskFilterSpan(MaskFilter filter):参数filter,滤镜样式。
说明:
在android系统里,MaskFilter提供了两个子类,BlurMaskFilter和EmbossMaskFilter,分别用来制作模糊效果和浮雕效果。
效果:

11.QuoteSpan

QuoteSpan,引用样式,在文本左侧添加一条表示引用的竖线,该类有3个构造函数:
QuoteSpan():无参构造,默认颜色为蓝色。
QuoteSpan(int color):参数color,颜色值。
QuoteSpan(Parcel src):包含颜色值信息的包装类。使用:
Parcel p = Parcel.obtain();
p.writeInt(Color.BLACK);
p.setDataPosition(0);
QuoteSpan qs = new QuoteSpan(p);
效果:

12.RasterizerSpan

RasterizerSpan,字面义为光栅化,实际效果不明显,待完善。一个构造函数:
RasterizerSpan(Rasterizer r):Rasterizer只有一个系统定义了的子类LayerRasterizer

13.RelativeSizeSpan

RelativeSizeSpan,相对大小,指相对于文本设定的大小的相对比例,如果没有设定则采用系统默认值。该类有两个构造函数:
RelativeSizeSpan(float proportion):参数proportion,比例值。如果文字设定大小为A,则显示出来的大小为A×proportion。
RelativeSizeSpan(Parcel src):参数src,包含了比例值信息的包装类。使用:
Parcel p = Parcel.obtain();
p.writeFloat(2.5f);
p.setDataPosition(0);
RelativeSizeSpan rss = new RelativeSizeSpan(p);
效果:

14.ScaleXSpan

ScaleXSpan,横向缩放样式,将字体按比例进行横向缩放。构造函数:
ScaleXSpan(float proportion):参数proportion,缩放比例。如果字体设置的大小为A,则实际显示为A×proportion。
ScaleXSpan(Parcel src):参数src,包含了缩放比例信息的包装类。使用:
Parcel p = Parcel.obtain();
p.writeFloat(2.5f);
p.setDataPosition(0);
ScaleXSpan rss = new ScaleXSpan(p);
效果:

15.StrikethroughSpan

StrikethroughSpan,删除线样式。该类有两个构造函数:
StrikethroughSpan()和SrickkethroughSapn(Parcel src)。但有参数的构造函数并未对src参数做处理,
public StrikethroughSpan(Parcel src) {
}
因此这两个构造函数完全是同样的效果。

16.StyleSpan

StyleSpan,主要由正常、粗体、斜体和同时加粗倾斜四种样式,常量值定义在Typeface类中。构造函数:
StyleSpan(int style):参数style,定义在Typeface中的常量。
StyleSpan(Parcel src):参数src,包含字体信息的包装类,用法:
Parcel p = Parcel.obtain();
p.writeInt(Typeface.BOLD_ITALIC);
p.setDataPosition(0);
StyleSpan ss = new StyleSpan(p);
效果:

17.SubscriptSpan

SubscriptSpan,脚注样式,比如化学式的常见写法,当然,还可以对脚注的文字做一定的缩放。构造函数:
SubscriptSpan():无参构造。
SubscriptSpan(Parcel src):一参构造,参数src并未起任何作用,源码中为:
public SuperscriptSpan(Parcel src) {
}
效果:

18.SuperscriptSpan

SuperscriptSpan,上标样式,比如数学上的次方运算,当然,还可以对上标文字进行缩放。构造函数:
SuperscriptSpan():无参构造。
SuperscriptSpan(Parcel src):一参构造,参数src并未起任何作用,源码中为:
public SuperscriptSpan(Parcel src) {
}
效果:

19.TabStopSpan

TabStopSpan.Standard,制表位偏移样式,距离每行的leading margin的偏移量,据测试在首行加入制表符时才产生效果。构造函数:
TabStopSpan.Standard(int where):参数where,偏移量。
效果:

20.TextAppearanceSpan

TextAppearanceSpan,使用style文件来定义文本样式,该类有4个构造函数:
TextAppearanceSpan(Context context, int appearance):参数context,传入的上下文,参数appearance,引用的样式表,如R.style.my_style。
TextAppearanceSpan(Context context, int appearance, int colorList):参数context,使用的上下文,参数appearance,引用的样式表,如R.style.my_style,参数colorList,使用方式未知,如果设置为小于0,则参数将不产生效果。
TextAppearanceSpan(String family, int style, int size,ColorStateList color, ColorStateList linkColor):参数family,字体,仅支持系统自带的三种字体,MONOSPACE、SERIF和SANS,参数style,TypeFace中定义的字体样式,BOLD、ITALIC等,参数size,字体大小,参数color,字体颜色,参数linkColor,使用方式未知。TextAppearanceSpan(Parcel src):参数src,含有样式信息的包装类,样式信息参照5参构造。使用:
Parcel p = Parcel.obtain();
p.writeString(\"SERIF\");
p.writeInt(Typeface.BOLD_ITALIC);
p.writeInt(10);
try {
    ColorStateList colorlist = ColorStateList.createFromXml(ctx.getResources(),ctx.getResources().getXml(R.drawable.parcelcolorlist));
    p.writeInt(1);
    colorlist.writeToParcel(p, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
    p.writeInt(1);
    colorlist.writeToParcel(p, Parcelable.PARCELABLE_WRITE_RETURN_VALUE);
} catch (Exception e) {
    e.printStackTrace();
}
p.setDataPosition(0);
TextAppearanceSpan tas = new TextAppearanceSpan(p);
注:在这个设置中style似乎并未起到作用,另外关于这个类的colorList和linkColor参数的使用尚不明了,有待解答。
效果:

21.TypefaceSpan

TypefaceSpan,字体样式,可以设置不同的字体,比如系统自带的SANS_SERIF、MONOSPACE和SERIF。构造函数:
TypefaceSpan(String family):参数family,字体的值,以字符串表示。
TypefaceSpan(Parcel src): 参数src,包含字体family信息的包装类,使用如下:
Parcel p = Parcel.obtain();
p.writeString(\"SERIF\");
p.setDataPosition(0);
TypefaceSpan ts = new TypefaceSpan(p);
 效果:

22.UnderlineSpan

UnderlineSpan,下划线样式,给一段文字加上下划线。构造函数:
UnderlineSpan(): 无参构造。
UnderlineSpan(Parcel src):一参构造, 与无参构造效果相同,构造中未对src做处理。源码:
public UnderlineSpan(Parcel src) {
}
效果:

23.URLSpan

URLSpan,可以打开一个链接。两个构造函数:
URLSpan(String url):参数url,链接地址。
URLSpan(Parcel src):参数src,包含链接地址信息的包装类,使用如下:
Parcel p = Parcel.obtain();
p.writeString("http://www.sina.com.cn");
p.setDataPosition(0);
URLSpan us = new URLSpan(p);
效果:

四、标注:

以上效果均在android2.3中测试,以后新增的几个类并未做说明,上面的类中还有几处使用的不甚明了的地方,希望能够尽快的完善。
以上所有的效果均写在了一个APK里,源码已上传至Android文本样式


  1. public class TextViewLinkActivity extends Activity {   
  2.     TextView mTextView = null;      
  3.     SpannableString msp = null;     
  4.        
  5.     /** Called when the activity is first created. */  
  6.     @Override  
  7.     public void onCreate(Bundle savedInstanceState) {   
  8.         super.onCreate(savedInstanceState);   
  9.         setContentView(R.layout.main);   
  10.            
  11.         mTextView = (TextView)findViewById(R.id.myTextView);   
  12.            
  13.         //创建一个 SpannableString对象     
  14.         msp = new SpannableString("字体测试字体大小一半两倍前景色背景色正常粗体斜体粗斜体下划线删除线x1x2电话邮件网站短信彩信地图X轴综合/bot");    
  15.            
  16.         //设置字体(default,default-bold,monospace,serif,sans-serif)   
  17.         msp.setSpan(new TypefaceSpan("monospace"), 02, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  18.         msp.setSpan(new TypefaceSpan("serif"), 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  19.            
  20.         //设置字体大小(绝对值,单位:像素)    
  21.         msp.setSpan(new AbsoluteSizeSpan(20), 46, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  22.         msp.setSpan(new AbsoluteSizeSpan(20,true), 68, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //第二个参数boolean dip,如果为true,表示前面的字体大小单位为dip,否则为像素,同上。   
  23.            
  24.         //设置字体大小(相对值,单位:像素) 参数表示为默认字体大小的多少倍   
  25.         msp.setSpan(new RelativeSizeSpan(0.5f), 810, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //0.5f表示默认字体大小的一半   
  26.         msp.setSpan(new RelativeSizeSpan(2.0f), 1012, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //2.0f表示默认字体大小的两倍   
  27.            
  28.         //设置字体前景色   
  29.         msp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 1215, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置前景色为洋红色   
  30.            
  31.         //设置字体背景色   
  32.         msp.setSpan(new BackgroundColorSpan(Color.CYAN), 1518, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置背景色为青色   
  33.         
  34.         //设置字体样式正常,粗体,斜体,粗斜体   
  35.         msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 1820, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //正常   
  36.         msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 2022, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗体   
  37.         msp.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 2224, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //斜体   
  38.         msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 2427, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗斜体   
  39.            
  40.         //设置下划线   
  41.         msp.setSpan(new UnderlineSpan(), 2730, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  42.            
  43.         //设置删除线   
  44.         msp.setSpan(new StrikethroughSpan(), 3033, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  45.            
  46.         //设置上下标   
  47.         msp.setSpan(new SubscriptSpan(), 3435, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //下标      
  48.         msp.setSpan(new SuperscriptSpan(), 3637, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   //上标               
  49.            
  50.         //超级链接(需要添加setMovementMethod方法附加响应)   
  51.         msp.setSpan(new URLSpan("tel:4155551212"), 3739, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //电话      
  52.         msp.setSpan(new URLSpan("mailto:webmaster@google.com"), 3941, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //邮件      
  53.         msp.setSpan(new URLSpan("http://www.baidu.com"), 4143, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //网络      
  54.         msp.setSpan(new URLSpan("sms:4155551212"), 4345, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //短信   使用sms:或者smsto:   
  55.         msp.setSpan(new URLSpan("mms:4155551212"), 4547, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //彩信   使用mms:或者mmsto:   
  56.         msp.setSpan(new URLSpan("geo:38.899533,-77.036476"), 4749, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //地图      
  57.            
  58.         //设置字体大小(相对值,单位:像素) 参数表示为默认字体宽度的多少倍   
  59.         msp.setSpan(new ScaleXSpan(2.0f), 4951, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //2.0f表示默认字体宽度的两倍,即X轴方向放大为默认字体的两倍,而高度不变   
  60.            
  61.         //设置字体(依次包括字体名称,字体大小,字体样式,字体颜色,链接颜色)   
  62.         ColorStateList csllink = null;   
  63.         ColorStateList csl = null;   
  64.         XmlResourceParser xppcolor=getResources().getXml (R.color.color);   
  65.         try {   
  66.             csl= ColorStateList.createFromXml(getResources(),xppcolor);   
  67.         }catch(XmlPullParserException e){   
  68.             // TODO: handle exception   
  69.             e.printStackTrace();           
  70.         }catch(IOException e){   
  71.             // TODO: handle exception   
  72.             e.printStackTrace();           
  73.         }   
  74.   
  75.         XmlResourceParser xpplinkcolor=getResources().getXml(R.color.linkcolor);   
  76.         try {   
  77.             csllink= ColorStateList.createFromXml(getResources(),xpplinkcolor);   
  78.         }catch(XmlPullParserException e){   
  79.             // TODO: handle exception   
  80.             e.printStackTrace();           
  81.         }catch(IOException e){   
  82.             // TODO: handle exception   
  83.             e.printStackTrace();           
  84.         }   
  85.         msp.setSpan(new TextAppearanceSpan("monospace",android.graphics.Typeface.BOLD_ITALIC, 30, csl, csllink), 5153, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);    
  86.         
  87.         //设置项目符号   
  88.         msp.setSpan(new BulletSpan(android.text.style.BulletSpan.STANDARD_GAP_WIDTH,Color.GREEN), 0 ,msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第一个参数表示项目符号占用的宽度,第二个参数为项目符号的颜色   
  89.   
  90.         //设置图片   
  91.         Drawable drawable = getResources().getDrawable(R.drawable.icon);    
  92.         drawable.setBounds(00, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());     
  93.         msp.setSpan(new ImageSpan(drawable), 5357, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   
  94.            
  95.         mTextView.setText(msp);   
  96.         mTextView.setMovementMethod(LinkMovementMethod.getInstance());    
  97.     }   
  98. }

参考:http://blog.csdn.net/lixin84915/article/details/8111337

    http://my.oschina.net/u/251121/blog/75078

0 0