SpannableString--让你的TextView装逼

TextView 应该是Android 中使用频率最高的控件之一,其重要性不言而喻

在平时的开发中,对于TextView的使用方法无非就是在layout 中设置一下布局、样式、颜色等,要是需要进行改变,丢到handler里

复杂一点的可以引入字体文件,通过资源进行设置

但是如果要在一定的范围内改变字体的样式怎么解决?拆分String,用两个TextView?

如果要让TextView实现类似于超链接的跳转功能怎么解决?添加监听事件,配合Intent使用?

再牛逼点,如果我要你TextView 显示图片,咋整? 啥?强转会报错?

现在,就正式请出今天的主角,SpannableString和SpannableStringBuilder

先说说二者的区别, SpannableString的长度固定,而SpannableStringBuilder的长度是可以改变的

本文着重就以SpannableString为例,至于SpannableStringBuilder的使用,我相信每个开发人员都懂得触类旁通,就不多介绍了

首先,我们先看下SpannableString的源码

public class SpannableString
extends SpannableStringInternal
implements CharSequence, GetChars, Spannable
{
    public SpannableString(CharSequence source) {
        super(source, 0, source.length());
    }

    private SpannableString(CharSequence source, int start, int end) {
        super(source, start, end);
    }

    public static SpannableString valueOf(CharSequence source) {
        if (source instanceof SpannableString) {
            return (SpannableString) source;
        } else {
            return new SpannableString(source);
        }
    }

    public void setSpan(Object what, int start, int end, int flags) {
        super.setSpan(what, start, end, flags);
    }

    public void removeSpan(Object what) {
        super.removeSpan(what);
    }

    public final CharSequence subSequence(int start, int end) {
        return new SpannableString(this, start, end);
    }
}

继承了抽象类SpannableStringInternal,和三个接口CharSequence, GetChars, Spannable

构造函数

public SpannableString(CharSequence source) {
        super(source, 0, source.length());
    }

参数就不多解释了

再看看setSpan方法

public void setSpan(Object what, int start, int end, int flags) {
        super.setSpan(what, start, end, flags);
    }

传入的参数有四个,这里解释下


/**
* what  字体设置的格式
* start 所设置字体的起始下标
* end   所设置结束下标
* flags 下标取值标志,取值:
* Spanned.SPAN_INCLUSIVE_EXCLUSIVE  从起始下标到结束下标,包括起始下标
* Spanned.SPAN_INCLUSIVE_INCLUSIVE  从起始下标到结束下标,同时包括起始下标和结束下标
* Spanned.SPAN_EXCLUSIVE_EXCLUSIVE  从起始下标到终了下标,但都不包括起始下标和结束下标
* Spanned.SPAN_EXCLUSIVE_INCLUSIVE  从起始下标到结束下标,包括结束下标
**/
有点拗口,但就是高中数学里交集并集的关系

如果实在不行,就看看我这边的栗子

package com.example.textviewdemo;

import android.app.Activity;
import android.graphics.Color;
import android.os.Bundle;
import android.text.Spannable;
import android.text.SpannableString;
import android.text.style.ForegroundColorSpan;
import android.widget.EditText;

public class MainActivity extends Activity {

	/**
	* what  字体设置的格式
	* start 所设置字体的起始下标
	* end   所设置结束下标
	* flags 下标取值标志,取值:
	* Spanned.SPAN_INCLUSIVE_EXCLUSIVE  从起始下标到结束下标,包括起始下标
	* Spanned.SPAN_INCLUSIVE_INCLUSIVE  从起始下标到结束下标,同时包括起始下标和结束下标
	* Spanned.SPAN_EXCLUSIVE_EXCLUSIVE  从起始下标到终了下标,但都不包括起始下标和结束下标
	* Spanned.SPAN_EXCLUSIVE_INCLUSIVE  从起始下标到结束下标,包括结束下标
	**/
	private EditText mEt1,mEt2,mEt3,mEt4;
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		initView();
	}
	private void initView(){
		mEt1 = (EditText)findViewById(R.id.et1);
		mEt2 = (EditText)findViewById(R.id.et2);
		mEt3 = (EditText)findViewById(R.id.et3);
		mEt4 = (EditText)findViewById(R.id.et4);
		
        //构造SpannableString  
        SpannableString spanString = new SpannableString("天王盖地虎宝塔镇河妖");    
        SpannableString spanString2 = new SpannableString("天王盖地虎宝塔镇河妖");
        SpannableString spanString3 = new SpannableString("天王盖地虎宝塔镇河妖");
        SpannableString spanString4 = new SpannableString("天王盖地虎宝塔镇河妖");
       //用于改变字体颜色的ForegroundColorSpan
        ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);    
        //设定范围,传入不同的flag
        spanString.setSpan(span, 1, 3, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);    
        spanString2.setSpan(span, 1, 3, Spannable.SPAN_INCLUSIVE_INCLUSIVE);    
        spanString3.setSpan(span, 1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);    
        spanString4.setSpan(span, 1, 3, Spannable.SPAN_EXCLUSIVE_INCLUSIVE);    
        //在不同的EditText中显示
        mEt1.setText(spanString);  
        mEt2.setText(spanString2);  
        mEt3.setText(spanString3);  
        mEt4.setText(spanString4);  
	}
}
然后分别在前后插入字符,效果如下

 


其他设置

上面的那颗栗子用到了设置颜色的类,但仅仅只能设置颜色,如何装逼?

        //改变字体背景色的span
        BackgroundColorSpan colorSpan = new BackgroundColorSpan(Color.BLUE);
//改变字体大小的span,传入一个int 值
        AbsoluteSizeSpan sizeSpan = new AbsoluteSizeSpan(16);   
        //设置文字相对大小的span,传入一个float,以原有字体的大小为基础设置倍数
        RelativeSizeSpan rSizeSpan = new RelativeSizeSpan(1.5f);
        //一些文本标志,以下划线为例
        UnderlineSpan lineSpan = new UnderlineSpan();

当然,除了这些,还有删除线(StrikethroughSpan) 文本样式(StyleSpan)等其他样式

上例的运行结果如图


介绍完样式使用,接下来隆重介绍两种更有逼格的用法

首先,试试在字段中加入一个超链接吧,代码如下

//超链接文本
        SpannableString spanString6 = new SpannableString("天王盖地虎宝塔镇河妖");
        URLSpan urlSpan = new URLSpan("http://www.baidu.com");
        spanString6.setSpan(urlSpan,1, 3, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        mTv1.setMovementMethod(LinkMovementMethod.getInstance());
        mTv1.setHighlightColor(Color.BLUE);
        mTv1.setText(spanString6);
运行效果:

点击后自动跳转页面,不用给TextView 添加监听事件,是不是很酷

你以为就这些功能?

前些天在倒腾聊天页面,要实现图片、文字的发送,文字用TextView 加到Item中即可,但是要在ListView 中显示图片就有些麻烦了。

我最开始的思路是在一个布局里同时存放ImageView 和TextView ,然后根据类型进行判断,将其设置为VISILIABLE 和GONE

但是这种方法使得适配器的代码过于冗长,而且findViewById 的开销有比较大,这才想到了也许可以用SpannableString来结局这个问题

废话少说,上代码

SpannableString spanString7 = new SpannableString("天王盖地虎宝塔镇河妖");
        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
        //设置图片大小
        drawable.setBounds(0, 0, 66, 66);
        ImageSpan imageSpan = new ImageSpan(drawable);
        spanString7.setSpan(imageSpan, 0, spanString7.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTv2.setText(spanString7);

上述所有的例子显示都如下图所示,顺便提一下聊天界面中Item 的思路,将接收到的图片保存至本地后将url保存到List中,首先判断数据的类型,如果是为图片,则直接将TextView 设置成该地址所对应的图片,将其显示出来,怎么样,是不是又方便又有逼格?

demo 下载



  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值