android中TextView的Spnnable使用

原创 2016年05月30日 18:24:02

项目中设计出的效果,我立即想到要使用SpannableString做出此效果。但我对SpannableString只是有基本的了解,下面我就记录下自己收集以及尝试的效果。

ApiDemo 源码至 com.example.android.apis.text.Link 类,可以看到text的不同效果。


一、自动应用效果,使用 android:autolink ="email|phone|web|map|all"属性

<!-- text1 automatically linkifies things like URLs and phone numbers. -->
      <TextView android:id="@+id/text1"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingBottom="8dp"
                android:autoLink="all"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/link_text_auto"
                />

点击数字,就会进入拨号页面;点击网址,就会在浏览器打开对应的网址;点击邮箱就进入发邮箱的功能;


二、在文本中使用 <a> 标签

 <string name="link_text_manual"><b>text2: Explicit links using <a> markup.</b>
      This has markup for a <a href="http://www.google.com">link</a> specified
      via an <a> tag.  Use a \"tel:\" URL
      to <a href="tel:4155551212">dial a phone number</a>.
    </string>

 <!-- text2 uses a string resource containing explicit <a> tags to
           specify links. -->
      <TextView android:id="@+id/text2"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:paddingTop="8dp"
                android:paddingBottom="8dp"
                android:textAppearance="?android:attr/textAppearanceMedium"
                android:text="@string/link_text_manual"
                />

    // text2 has links specified by putting <a> tags in the string
        // resource.  By default these links will appear but not
        // respond to user input.  To make them active, you need to
        // call setMovementMethod() on the TextView object.

        TextView t2 = (TextView) findViewById(R.id.text2);
        t2.setMovementMethod(LinkMovementMethod.getInstance());


三、第三种和第二种其实是一样的,只不过将文本改在 JAVA 代码中

 // text3 shows creating text with links from HTML in the Java
        // code, rather than from a string resource.  Note that for a
        // fixed string, using a (localizable) resource as shown above
        // is usually a better way to go; this example is intended to
        // illustrate how you might display text that came from a
        // dynamic source (eg, the network).

        TextView t3 = (TextView) findViewById(R.id.text3);
        t3.setText(
            Html.fromHtml(
                "<b>text3: Constructed from HTML programmatically.</b>  Text with a " +
                "<a href=\"http://www.google.com\">link</a> " +
                "created in the Java source code using HTML."));
        t3.setMovementMethod(LinkMovementMethod.getInstance());

四、通过创建 SpanableString 字符串,并在之上创 建一个或多个 Span 来实现丰富的效果。

SpannableString的定义:

This is the class for text whose content is immutable but to which markup objects can be attached and detached. For mutable text, see SpannableStringBuilder.
<span style="color:#FF0000;"><strong>翻译:SpannableString</strong>是文本内容不可改变,但标记对象可以绑定和解绑的类。</span>

官方文档中前半句话好理解,后半句就不怎么好理解了。问题就来了:

  • 什么是标记对象呢(markup objects)?
  • 绑定和解绑(attached and detached)又是什么意思呢?
标记对象

标记语言(也称置标语言、标记语言、标志语言、标识语言)是一种将文本(Text)以及文本相关的其他信息结合起来,展现出关于文档结构和数据处理细节的计算机文字编码。至于标记对象则是和标记语言一个意思,就是能设置文本的各种样式的方法。


例子如下:

link_color的写法如下:

<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android" >
    <item android:state_pressed="true"
          android:color="#ffff00"/> <!-- pressed -->
    <item android:state_focused="true"
          android:color="#ffff00"/> <!-- focused -->
    <item android:color="#ff0000"/> <!-- default -->

</selector>

java代码如下:

textView =(TextView) findViewById(R.id.textview);
		//使用setSpan(Object what, int start, int end, int flags)方法设置标记对象,其中长度是end-start。
	    //使用removeSpan()解绑标记对象
	    //public void setSpan (Object what, int start, int end, int flags)
	    //绑定特定的标记对象(Object what)到起始为start,终止为end的text对象上(若已绑定标记对象则先移除)
	    //设置字体TypefaceSpan()
	    //设置字体大小(绝对值)AbsoluteSizeSpan()
	    //设置字体大小(相对值)RelativeSizeSpan()
	    //设置字体大小(相对值,默认字体宽度的倍数)ScaleXSpan()
	    //设置字体的前景色ForegroundColorSpan()
	    //设置字体的背景色BackgroundColorSpan()
	    //设置字体的样式StyleSpan()
	    //设置下划线UnderlineSpan()
	    //删除线StrikethroughSpan()
	    //上标SuperscriptSpan()
	    //下标SubscriptSpan()
	    //链接URLSpan()-->需要添加setMovementMethod方法附加响应
	    //字体外观设置(依次包括字体名称,字体大小,字体样式,字体颜色,链接颜色)TextAppearanceSpan()
	    //项目符号BulletSpan()
	    //图片ImageSpan()
		//android.text.style.XXX 获取各种span的Parcel属性

		  //创建一个 SpannableString对象  
        msp = new SpannableString("字体测试字体大小一半两倍前景色背景色正常粗体斜体粗斜体下划线删除线x1x2电话邮件网站短信彩信地图X轴综合/bot"); 
        
        //设置字体(default,default-bold,monospace,serif,sans-serif)
        msp.setSpan(new TypefaceSpan("monospace"), 0, 2, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        msp.setSpan(new TypefaceSpan("serif"), 2, 4, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        //设置字体大小(绝对值,单位:像素) 
        msp.setSpan(new AbsoluteSizeSpan(20), 4, 6, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
       //第二个参数boolean dip,如果为true,表示前面的字体大小单位为dip,否则为像素,同上。
        msp.setSpan(new AbsoluteSizeSpan(20,true), 6, 8, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  
        
        //设置字体大小(相对值,单位:像素) 参数表示为默认字体大小的多少倍
        msp.setSpan(new RelativeSizeSpan(0.5f), 8, 10, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //0.5f表示默认字体大小的一半
        msp.setSpan(new RelativeSizeSpan(2.0f), 10, 12, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //2.0f表示默认字体大小的两倍
        
        //设置字体前景色
        msp.setSpan(new ForegroundColorSpan(Color.MAGENTA), 12, 15, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置前景色为洋红色
        
        //设置字体背景色
        msp.setSpan(new BackgroundColorSpan(Color.GREEN), 15, 18, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //设置背景色为青色
     
        //设置字体样式正常,粗体,斜体,粗斜体
        msp.setSpan(new StyleSpan(android.graphics.Typeface.NORMAL), 18, 20, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //正常
        msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD), 20, 22, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗体
        msp.setSpan(new StyleSpan(android.graphics.Typeface.ITALIC), 22, 24, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //斜体
        msp.setSpan(new StyleSpan(android.graphics.Typeface.BOLD_ITALIC), 24, 27, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);  //粗斜体
        
        //设置下划线
        msp.setSpan(new UnderlineSpan(), 27, 30, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        //设置删除线
        msp.setSpan(new StrikethroughSpan(), 30, 33, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        //设置上下标
        msp.setSpan(new SubscriptSpan(), 34, 35, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //下标   
        msp.setSpan(new SuperscriptSpan(), 36, 37, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);   //上标            
        
        //超级链接(需要添加setMovementMethod方法附加响应)
        msp.setSpan(new URLSpan("tel:4155551212"), 37, 39, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //电话   
        msp.setSpan(new URLSpan("mailto:webmaster@google.com"), 39, 41, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //邮件   
        msp.setSpan(new URLSpan("http://www.baidu.com"), 41, 43, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //网络   
        msp.setSpan(new URLSpan("sms:4155551212"), 43, 45, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //短信   使用sms:或者smsto:
        msp.setSpan(new URLSpan("mms:4155551212"), 45, 47, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //彩信   使用mms:或者mmsto:
        msp.setSpan(new URLSpan("geo:38.899533,-77.036476"), 47, 49, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);     //地图   
        
        //设置字体大小(相对值,单位:像素) 参数表示为默认字体宽度的多少倍
      //2.0f表示默认字体宽度的两倍,即X轴方向放大为默认字体的两倍,而高度不变
        msp.setSpan(new ScaleXSpan(2.0f), 49, 51, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
        
        //设置字体(依次包括字体名称,字体大小,字体样式,字体颜色,链接颜色)
        ColorStateList csllink = null;
        ColorStateList csl = null;
        XmlResourceParser xppcolor=getResources().getXml(R.drawable.link_color);
        try {
        	csl= ColorStateList.createFromXml(getResources(),xppcolor);
        	csllink= ColorStateList.createFromXml(getResources(),xppcolor);
        }catch(XmlPullParserException e){
        	e.printStackTrace();    	
        }catch(IOException e){
        	e.printStackTrace();    	
        }
        msp.setSpan(new TextAppearanceSpan("monospace",android.graphics.Typeface.BOLD_ITALIC, 30, csl, csllink), 51, 53, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); 
        
        //设置项目符号
        msp.setSpan(new BulletSpan(android.text.style.BulletSpan.CONTENTS_FILE_DESCRIPTOR,Color.RED), 0 ,msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //第一个参数表示项目符号占用的宽度,第二个参数为项目符号的颜色

        //设置图片
        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher); 
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());  
        msp.setSpan(new ImageSpan(drawable), 53, 57, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        
        textView.setText(msp);
        textView.setMovementMethod(LinkMovementMethod.getInstance()); 

效果如下:



最后有几个点要说明:

1)许多span都有XXXSpan(Parcel src)的构造方法,在android.text.style.XXX.XXX中获取各种span的Parcel属性

 2) setSpan(Object what, int start, int end, int flags)中的flag有几个值:

SPAN_INCLUSIVE_EXCLUSIVE(前后都包括): [0,5]

SPAN_INCLUSIVE_INCLUSIVE(前面包括,后面不包括):[0,5)

SPAN_EXCLUSIVE_EXCLUSIVE(前后都不包括):(0,5)

SPAN_EXCLUSIVE_INCLUSIVE(前面不包括,后面包括):(0,5]

3)使用TextAppearanceSpan时,color必须是selector类型。

/**
     * Makes text be drawn with the specified typeface, size, style,
     * and colors.
     */
    public TextAppearanceSpan(String family, int style, int size,
                              ColorStateList color, ColorStateList linkColor) {
        mTypeface = family;
        mStyle = style;
        mTextSize = size;
        mTextColor = color;
        mTextColorLink = linkColor;
    }


SpnnableString 初体验

SpannableString 的简单使用 在项目中遇到了这样的一个需求:用一个TextView显示不同颜色的字符 使用SpannableString 可达到要求。SpannableString ...
  • lygirl3721
  • lygirl3721
  • 2017年10月06日 22:43
  • 143

android中TextView的Spnnable使用

项目中设计出的效果,我立即想到要使用SpannableString做出此效果。但我对SpannableString只是有基本的了解,下面我就记录下自己收集以及尝试的效果。 ApiDemo 源码至 c...
  • wuyou1336
  • wuyou1336
  • 2016年05月30日 18:24
  • 1463

Android中TextView通过SpannableString设置字体、大小、颜色、样式、超级链接

直接贴代码,不知道怎么使用的看注释吧。
  • lukejun1988
  • lukejun1988
  • 2014年05月15日 15:20
  • 10615

TextView占位符

引子: 如果一段文字需要多段TextView拼接而成,比如:“我叫XXX,今年XX岁了,身高X.X米”。 拿到这样的需求可能我们第一反应就是StringBuilder的append(也许是因为...
  • lingdianalex
  • lingdianalex
  • 2016年09月19日 09:39
  • 2422

Android学习之Textview的使用

TextView显示文本控件 示例一:显示文本(url、不同大小、字体、颜色) 示例二:单击链接弹出Activity 示例三:使用TextView实现跑马灯的效果 示例一:...
  • qq_28468727
  • qq_28468727
  • 2016年08月19日 23:42
  • 2280

Android文本样式——上

在android中,有时候需要对文本进行各种特别的设置,比如颜色、大小、首行缩进,或者是在一段文本中加入图片,甚至是书写一些特殊的公式。如果通过布局文件使用多个控件来实现,一方面会使的使用起来特别的复...
  • lixin84915
  • lixin84915
  • 2012年10月25日 15:35
  • 8324

Android-MTK系统- 系统常用修改点

Android-MTK系统- 系统常用修改点
  • gjy_it
  • gjy_it
  • 2017年06月26日 11:58
  • 752

TextView常用的几种方式:占位符(一)

前言: 以前写过关于TextView的相关内容,但是觉得没有把他们给整理出来,有点凌乱,所以在这里再次花时间把TextView常用的几种方式再次整理出来让大家参考! 功能: 本文主要是完成类似京东套...
  • jayliu1989
  • jayliu1989
  • 2017年03月22日 08:50
  • 1990

android 单个textview 中显示多种style

效果图 在style中定义两个sytle 14dp #4d7bae 14dp ...
  • baidu_26834727
  • baidu_26834727
  • 2015年04月24日 11:18
  • 512

android 各个span类详解--用于富文本的编排 上

在android中,有时候需要对文本进行各种特别的设置,比如颜色、大小、首行缩进,或者是在一段文本中加入图片,甚至是书写一些特殊的公式。如果通过布局文件使用多个控件来实现,一方面会使的使用起来特别的复...
  • licx11
  • licx11
  • 2014年11月24日 10:47
  • 2664
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:android中TextView的Spnnable使用
举报原因:
原因补充:

(最多只允许输入30个字)