经典使用场景
SpannableStringBuilder needStartSSB = new SpannableStringBuilder("需要");
SpannableString mSpannableString = new SpannableString("多少");

//颜色
ForegroundColorSpan colorSpan = new ForegroundColorSpan(0xffffa726);
mSpannableString.setSpan(colorSpan, 0, mSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
//大小
AbsoluteSizeSpan absoluteSizeSpan = new AbsoluteSizeSpan(ApplicationUtil.dip2px(15));
mSpannableString.setSpan(absoluteSizeSpan, 0, mSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);

needStartSSB.append(mSpannableString).append("财富值");  

富文本类简介

设置富文本信息的几种方式:

  • 1、拼接多个TextView,如果此富文本信息中多个字段是独立的,可以采取这种方式,否则这种方式是繁琐且不合理的
  • 2、使用Html.fromHtml(),此方法可以转换html格式的字符串为Android支持的字符串,简单的颜色,下划线,粗体及链接是比较方便的,但是有些标签可能会不兼容,另外注意某些特殊符号,特别是双引号,需要在前面添加转义字符。
  • 3、可以在布局中直接定义Html类型的富文本样式,注意,只能在values/strings文件中定义,否则不起作用,另外,这种方式支持的标签数比上面代码中的还少,但是对于一些简单的样式,特别是下划线,这种方式是最方便的。
  • 4、使用SpannableString和SpannableStringBuilder类,使用这种方式可以灵活的设置复杂的富文本样式,但是代码量偏多,下面详细介绍这种方式。
简介
  • SpannableString和SpannableStringBuilder相比,SpannableString像String一样,构造对象的时候传入一个String之后无法更改String的内容,也无法拼接多个 SpannableString;而SpannableStringBuilder则像是StringBuilder,它可以通过其append()方法来拼接多个SpannableString。
  • 因为Spannable实现了CharSequence接口,所以可以直接把SpannableString和SpannableStringBuilder通过TextView.setText(CharSequence)设置给TextView
  • 注意不能将SpannableString或SpannableStringBuilder通过toString或【+"字符串"】,否则富文本就变成纯文本了。
  • 另外,由于TextView具有tv.append(CharSequence)方法,所以在给TextView设置多个富文本信息时,也可采用append()多个SpannableString的方式,具体详见示例代码。
API的Class General Hierarchy:
     

设置样式setSpan

SpannableString和SpannableStringBuilder都有一个设置Span的方法:setSpan(Object what, int start, int end, int flags);

  • 参数what是要设置的Span ;
  • start和end则是标识此String中需要应用Span的起始位置(0表示第一个字符,包含开始不包含结尾),注意:范围超出文字大小时会报异常
  • 而 flags是用来标识在 Span 范围内的文本【前后】输入【新】的字符时是否把它们也应用这个效果,我们一般都是用 Spanned.SPAN_EXCLUSIVE_EXCLUSIVE
自带的 flags有(其中EXCLUSIVE代表不包含,INCLUSIVE代表包含)
  • Spanned.SPAN_EXCLUSIVE_EXCLUSIVE --- 不包含两端start和end所在的端点
  • Spanned.SPAN_EXCLUSIVE_INCLUSIVE --- 不包含端start,但包含end所在的端点
  • Spanned.SPAN_INCLUSIVE_EXCLUSIVE --- 包含端start,但不包含end所在的端点
  • Spanned.SPAN_INCLUSIVE_INCLUSIVE--- 包含两端start和end所在的端点
 常见的Span类型
  • ForegroundColorSpan 文本颜色
  • URLSpan 文本超链接,要设置setMovementMethod(LinkMovementMethod.getInstance())才可响应点击
  • BackgroundColorSpan 背景色
  • UnderlineSpan 下划线
  • AbsoluteSizeSpan 绝对大小(文本字体),一般是将dp2px转换后的值传给他
  • ClickableSpan 文本可点击,有点击事件
  • MaskFilterSpan 修饰效果,如模糊(BlurMaskFilter)、浮雕(EmbossMaskFilter)
  • MetricAffectingSpan 父类,一般不用
  • RasterizerSpan 光栅效果
  • StrikethroughSpan 删除线(中划线)
  • SuggestionSpan 相当于占位符
  • DynamicDrawableSpan 设置图片,基于文本基线或底部对齐。
  • ImageSpan 图片
  • RelativeSizeSpan 文本字体相对大小,参数是相对于默认字体大小的倍数
  • ReplacementSpan 父类,一般不用
  • ScaleXSpan 基于x轴缩放
  • StyleSpan 字体样式:粗体、斜体等,参数是android.graphics.Typeface里面定义的常量
  • SubscriptSpan 下标(数学公式会用到)
  • SuperscriptSpan 上标(数学公式会用到)
  • TextAppearanceSpan 文本外貌(包括字体、大小、样式和颜色)
  • TypefaceSpan 文本字体,参数是字体的名字比如“sans", "sans-serif"等

演示代码

public class MainActivity extends Activity {

    private TextView tv1;
    private TextView tv2;
    private TextView tv3;
    private TextView tv4;
    private TextView tv5;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        tv1 = (TextView) findViewById(R.id.tv1);
        tv2 = (TextView) findViewById(R.id.tv2);
        tv3 = (TextView) findViewById(R.id.tv3);
        tv4 = (TextView) findViewById(R.id.tv4);
        tv5 = (TextView) findViewById(R.id.tv5);
        setForegroundColor();
        setBackgroundColor();
        setStyle();
        setSize();
        setLink();
    }
    //文字颜色,标准写法一
    private void setForegroundColor() {
        SpannableString spanString = new SpannableString("文字颜色 ");
        ForegroundColorSpan span = new ForegroundColorSpan(Color.BLUE);//常用values/colors中定义的颜色
        spanString.setSpan(span, 0, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        //tv1.setText(spanString, BufferType.SPANNABLE);//一般不用设置后面的参数,但有时必须使用这种格式
        tv1.setText(spanString);
    }
    //背景色
    private void setBackgroundColor() {
        tv2.setText("应付:");
        SpannableString spanString = new SpannableString("888");
        BackgroundColorSpan span = new BackgroundColorSpan(0x88008800);
        spanString.setSpan(span, 0, spanString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        //    tv2.append(spanString + " 元");//这样是不行的,因为【spanString + " 元"】的结果是一个没有格式的字符串
        tv2.append(spanString);//这样是可以的
        tv2.append(" 元");
    }
    //粗体、斜体、删除线、下划线,使用多个SpannableString设置多个富文本样式
    private void setStyle() {
        tv3.setText("样式:");
        SpannableString mSpannableString1 = new SpannableString("粗体 ");
        StyleSpan mStyleSpan = new StyleSpan(Typeface.BOLD);
        mSpannableString1.setSpan(mStyleSpan, 0, mSpannableString1.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv3.append(mSpannableString1);
        SpannableString mSpannableString2 = new SpannableString("删除线 ");
        StrikethroughSpan mStrikethroughSpan = new StrikethroughSpan();
        mSpannableString2.setSpan(mStrikethroughSpan, 0, mSpannableString2.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv3.append(mSpannableString2);
        SpannableString mSpannableString3 = new SpannableString("下划线");
        UnderlineSpan mUnderlineSpan = new UnderlineSpan();
        mSpannableString3.setSpan(mUnderlineSpan, 0, mSpannableString3.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        tv3.append(mSpannableString3);
    }
    //文字链接,使用一个SpannableStringBuilder及多个SpannableString设置多个富文本样式
    private void setLink() {
        SpannableStringBuilder mSpannableStringBuilder = new SpannableStringBuilder("链接:电话 ");
        URLSpan mUrlSpan = new URLSpan("tel:110");//会把参数通过intent的putExtra的参数传进去,注意格式!
        mSpannableStringBuilder.setSpan(mUrlSpan, 3, mSpannableStringBuilder.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        SpannableString mSpannableString2 = new SpannableString("网址 ");
        URLSpan mUrlSpan2 = new URLSpan("http://www.baidu.com");
        mSpannableString2.setSpan(mUrlSpan2, 0, mSpannableString2.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        mSpannableStringBuilder.append(mSpannableString2);
        SpannableString mSpannableString3 = new SpannableString("邮箱 ");
        URLSpan mUrlSpan3 = new URLSpan("mailto:bqt@sina.com");
        mSpannableString3.setSpan(mUrlSpan3, 0, mSpannableString3.length() - 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        mSpannableStringBuilder.append(mSpannableString3);
        SpannableString mSpannableString4 = new SpannableString("短信");
        URLSpan mUrlSpan4 = new URLSpan("smsto:10086");
        mSpannableString4.setSpan(mUrlSpan4, 0, mSpannableString4.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
        mSpannableStringBuilder.append(mSpannableString4);
        tv4.setText(mSpannableStringBuilder);
        tv4.setMovementMethod(LinkMovementMethod.getInstance());//要设置这个东东才能点击
    }
    //字号
    private void setSize() {
        tv5.setText("字号:");
        SpannableStringBuilder mSpannableStringBuilder = new SpannableStringBuilder("相对大小 ");
        RelativeSizeSpan mRelativeSizeSpan = new RelativeSizeSpan(0.5f);
        mSpannableStringBuilder.setSpan(mRelativeSizeSpan, 0, mSpannableStringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        SpannableString mSpannableString = new SpannableString("绝对大小");
        AbsoluteSizeSpan span = new AbsoluteSizeSpan(dp2px(20));
        mSpannableString.setSpan(span, 0, mSpannableString.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        mSpannableStringBuilder.append(mSpannableString);
        tv5.append(mSpannableStringBuilder);
    }
    /** 
    * 根据手机的分辨率从 dp 的单位 转成为 px(像素) 
    */
    public int dp2px(float dpValue) {
        float scale = getResources().getDisplayMetrics().density;
        return (int) (dpValue * scale + 0.5f);
    }

}


演示布局


<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#fff"
    android:orientation="vertical"
    android:padding="10dp" >
    <TextView
        android:id="@+id/tv1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv3"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv4"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />
    <TextView
        android:id="@+id/tv5"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content" />

</LinearLayout>


图片--可以实现图文混排的效果

需求:在文字后面加上一个图标

tv = (TextView) findViewById(R.id.tv);

        String text = "哈哈★我能把★换成图片";
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        Pattern pattern = Pattern.compile("★");
        Matcher matcher = pattern.matcher(text);
        while (matcher.find()) {
            //不能在while循环外定义ImageSpan,否则只会把最后一个★替换掉
            builder.setSpan(new ImageSpan(this, R.drawable.ic_launcher), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        tv.setGravity(Gravity.CENTER);//无效!不知道怎么解决

tv.setText(builder);  


tv = (TextView) findViewById(R.id.tv);

        String text = "哈哈★我能把★换成图片";
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        Pattern pattern = Pattern.compile("★");
        Matcher matcher = pattern.matcher(text);
        Drawable drawable = getResources().getDrawable(R.drawable.ic_launcher);
        //必须为drawable设置边界(下面的就是标准格式),否则图片不会显示
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());
        while (matcher.find()) {
            //不能在while循环外定义ImageSpan,否则只会把最后一个★替换掉
            builder.setSpan(new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE), matcher.start(), matcher.end(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
        }
        tv.setGravity(Gravity.CENTER);//无效!不知道怎么解决

tv.setText(builder);


富文本 SpannableString Span的更多相关文章

  1. Vue富文本编辑器(图片拖拽缩放)

    富文本编辑器(图片拖拽缩放) 需求: 根据业务要求,需要能够上传图片,且上传的图片能在移动端中占满屏幕宽度,故需要能等比缩放上传的图片,还需要能拖拽.缩放.改变图片大小.尝试多个第三方富文本编辑器,很 ...

  2. springmvc 后台实体类接受前端json字符串时,其中一个属性content 接受富文本内容时 标签<p>、<span> 这些标签丢失问题解决

    问题描述: 前端一个字段 <script id="editor" type="text/plain" name="content" s ...

  3. SpannableString富文本

    忍不住想吐槽这个类,这个类是要给文本设置不同的颜色.字体样式 例子:一句话中只有某几个文字想要设置成不同的颜色 起初写了一个函数setColorStyle(), public SpannableStr ...

  4. TextView展示富文本时emoj或图片和文字不对齐的解决方案

    在项目中,回复框.聊天界面的显示往往会有emoj或者图片,但是一个比较头疼的问题是,会出现emoj表情或者图片和文字的位置不对齐,总是有偏移,这样很影响用户体验的.下面会总结一下如何解决这个问题. 本 ...

  5. Android - 富文本编辑器

    Android富文本编辑器(一):基础知识 目前主流的基于Android富文本开发方式思路如下: 基于TextView图文混排 使用方式: TextView textView = new TextVi ...

  6. 个人网站对xss跨站脚本攻击(重点是富文本编辑器情况)和sql注入攻击的防范

    昨天本博客受到了xss跨站脚本注入攻击,3分钟攻陷--其实攻击者进攻的手法很简单,没啥技术含量.只能感叹自己之前竟然完全没防范. 这是数据库里留下的一些记录.最后那人弄了一个无限循环弹出框的脚本,估计 ...

  7. 富文本编辑器kindeditor配置

    <!--富文本编辑器kindeditor配置↓ --> <link type="text/css" rel="stylesheet" href ...

  8. 富文本编辑器防止xss注入javascript版

    富文本编辑器:ueditor 其实富文本编辑器已经有防止xss注入功能,但是你服务端程序在接收的时候在做一次转义,否则有可能然后前端验证直接提交数据导致被xss攻击. 为了节省后端程序开销则在前端 显 ...

  9. 对于MVC中应用百度富文本编辑器问题的解决办法

    1.对于应用富文本编辑器post提交表单内容提示有危险的解决办法: [ValidateInput(false)] //文本编辑器的表单提交不用提示危险 [HttpPost] public Action ...

随机推荐

  1. 《asp.net mvc3 高级编程》第四章 模型

    一,建立简单的Model 在Models文件夹上右击鼠标,选择“添加”,“类”,如下图所示: 建立三类相关联的类代码如下: public class Album { public virtual in ...

  2. 如何把PPT变小|PowerPoint文档减肥的几种方法

    使用powerpoint制作幻灯片的过程中,经常出现过这样的情况,制作幻灯片时,出于内容的需要和美观的需要,添加了许多图片和Excel表或者OLE对象,成倍增大了文档的体积,结果导致: 1.页面编辑人 ...

  3. UI基础 - UIScrollView

    scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(, , , )]; scrollView.backgroundColor = [ ...

  4. 关于 从别人电脑上 高版本的 Xcode上拷贝过来的项目的 不能运行模拟器的 解决方法

    如图 从别人电脑上 拷贝过来的  工程  打开后  点击 iOS  Device  只有  一个选项  没有模拟器.这说明 自己的 Xcode 的版本比 创建这个工程所用的版本低.所以 要睇啊你tar ...

  5. stringstream复用【原创】

    stringstream ss("123"); int i=0; ss>>i;   ss.str("");        ----清空内容 ss.c ...

  6. css+div 布局遇到的小常识

    /根目录../上层目录举例如下: 在photo.css文件中写入: div.ls{ background:url(../photo/framels.jpg) no-repeat left; }div. ...

  7. 值得收藏的Javascript代码

    1  Javascript数组转换为CSV格式 首先考虑如下的应用场景,有一个Javscript的字符型(或者数值型)数组,现在需要转换为以逗号分割的CSV格式文件.则我们可以使用如下的小技巧,代码如 ...

  8. [Java] 继承中,父类被覆盖的成员变量、方法的可访问性

    在 Java 的继承机制里,在子类内部,可以访问父类被覆盖的变量和方法:在子类外部,可以访问父类的被覆盖变量,但是不能访问父类的被覆盖方法. 父类中被覆盖的方法不能在外部被方法,这是出于封装的考虑. ...

  9. SRM468 - SRM469(1-250pt, 500pt)

    SRM 468 DIV1 250pt 题意:给出字典,按照一定要求进行查找. 解法:模拟题,暴力即可. tag:water score: 0.... 这是第一次AC的代码: /* * Author: ...

  10. struts接收参数方式

    第一种,直接用action的属性接收,是初学者常用的方法. package com.starain.user; public class User{ private String username; ...