观心静

  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

版权声明

本文来自博客园,作者:观心静 ,转载请注明原文链接:https://www.cnblogs.com/guanxinjing/p/11227711.html

本文版权归作者和博客园共有,欢迎转载,但必须给出原文链接,并保留此段声明,否则保留追究法律责任的权利。

前言

  SpannableString,是google提供用来处理富文本的功能类.支持很多文本内容的效果变化.另外,它也是Android实现富文本编辑器的关键.

  SpannableStringBuilder是用于实现多个SpannableString拼接的实现类,类似于Java的StringBuilder。此类下面也会简单说明,主要还是了解SpannableString。

关键API详解

     String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#FFFF0C00"))
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

这是一个简单使用的demo,我们用这个demo来讲解一些关键点.

这行代码的关键是setSpan(Object what, int start, int end, int flags)方法,这个方法在后面的文字处理将会一直使用到. setSpan有四个参数我们一个一个来讲解:

第一个参数 Object what 这个参数主要是提供你需要改变字符串的效果实现类,后续会一一讲解并且给出效果图

第二个参数 int start 这个参数是需要改变的字符串的起始位置

第三个参数 int end 这个参数是需要改变的字符串的结束位置

第四个参数 int flags 是一些字符串新增效果的影响范围,您可以参考这篇博客https://www.jianshu.com/p/1956e15c9a27这位大神讲解的十分详细了.本着就算是看懂了也要敲一敲代码记录的想法,下面也会说明一下常用的4种方法

public static final int SPAN_INCLUSIVE_EXCLUSIVE = SPAN_MARK_MARK; 

在前面/范围内增加字符,新增字符会跟随效果.

在后面增加字符,新增字符不会跟随效果

效果图:

 

public static final int SPAN_INCLUSIVE_INCLUSIVE = SPAN_MARK_POINT;

在前面/范围内/后面增加字符,新增字符会跟随效果.

效果图:

public static final int SPAN_EXCLUSIVE_EXCLUSIVE = SPAN_POINT_MARK;

在范围内增加字符,新增字符会跟随效果.

在前面/后面增加字符,新增字符不会跟随效果

效果图:

public static final int SPAN_EXCLUSIVE_INCLUSIVE = SPAN_POINT_POINT;

在范围内/后面增加字符,新增字符会跟随效果.

在前面增加字符,新增字符不会跟随效果.

效果图:

 

代码里还有一些其他的常量,但是测试后其他都是这四种基本里一样的效果.也实在是没看懂google的注释.....

文字颜色

以下代码将一段文字变成红色

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new ForegroundColorSpan(Color.parseColor("#FFFF0C00"))
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);    

 

ForegroundColorSpan 注意这个类是关键,他实现文字颜色改变.

效果图:

文字背景颜色

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new BackgroundColorSpan(Color.parseColor("#FFFF0C00"))
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

BackgroundColorSpan 注意这个类是关键,他实现文字背景颜色改变.

效果图:

字体

 

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new TypefaceSpan("sans-serif") //new TypefaceSpan(Typeface.SANS_SERIF) 或者使用这个方法
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

效果图(系统自带的演示字体效果不明显):

 

字体大小

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new AbsoluteSizeSpan(50)
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);    

 

效果图:

 

粗体

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new StyleSpan(Typeface.BOLD)
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

效果图:

斜体

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new StyleSpan(Typeface.ITALIC)
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

效果图:

粗体和斜体

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new StyleSpan(Typeface.BOLD_ITALIC)
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

另外还有一个Typeface.NORMAL  正常值就不演示了

效果图:

 

删除线

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new StrikethroughSpan()
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

 

效果图:

 

 

下划线

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new UnderlineSpan()
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

效果图:

上标

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new SuperscriptSpan()
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

效果图:

下标

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new SubscriptSpan()
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

效果图:

插入图片

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
        ImageSpan span = new ImageSpan(bitmap);
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(span
                , 0
                , 1
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

或者

        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        Drawable drawable = getResources().getDrawable(R.mipmap.ic_launcher, null); //读取图片
        drawable.setBounds(0, 0, drawable.getIntrinsicWidth(), drawable.getIntrinsicHeight());//设置边界 图片显示范围
        ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BASELINE);//ImageSpan.ALIGN_BASELINE 是对齐方式,这个是基线对齐
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(span
                , 0
                , 1
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

效果图:

点击事件

        mTextView.setMovementMethod(LinkMovementMethod.getInstance());//这是关键,只有TextView添加这个后才能有点击事件
        mTextView.setHighlightColor(getResources().getColor(R.color.fontRed, null));//修改点击后的背景色
        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        ClickableSpan clickableSpan = new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
                Toast.makeText(MainActivity.this, "你点击了创业未半", Toast.LENGTH_SHORT).show();
            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                //改变选中文字的颜色或者样式,注意这里的TextPaint 其实是Paint,可以参考Paint的绘制添加其他效果.
                ds.setColor(Color.RED);
//                super.updateDrawState(ds);
            }
        };
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(clickableSpan
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

setMovementMethod是重中之重,只有设置了才能有 点击功能

另外,如果你需要设置文字的各种样式,比如 取消下划线 ds.setUnderlineText(false) 改变 字体颜色 请在updateDrawState(@NonNull TextPaint ds) 方法里设置

效果图:

超链接

 电话

        mTextView.setMovementMethod(LinkMovementMethod.getInstance());//这是关键,只有TextView添加这个后才能有点击事件
        mTextView.setHighlightColor(getResources().getColor(R.color.fontRed, null));//修改点击后的背景色
        String content ="先帝创业未半而中道崩殂,今天下三分,益州疲弊,此诚危急存亡之秋也。";
        SpannableString spannableString = new SpannableString(content);
        spannableString.setSpan(new URLSpan("tel:10086")
                , content.indexOf("创业")
                , content.indexOf("而中")
                , Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        mTextView.setText(spannableString);

注意!使用超链接,依然要设置setMovementMethod,另外URLSpan也是可以重写点击事件的.

 效果图:

 

与使用Intent的超链接类似,也是支持几个通用的超链接,都需要你输入正确的前缀

  • mailto:123456@qq.com
  • http://www.baidu.com
  • sms:123456
  • mms:123456
  • geo: 38.899533,-77.036476

 

SpannableStringBuilder 的功能使用

这个类是用于实现多个SpannableString文字拼接的。这里举一个例子进行说明,假如我们要实现下面图片的效果:

用户协议与隐私政策需要分别的点击效果。

代码如下:

    private void initAgreementAndPrivacy() {
        SpannableStringBuilder builder = new SpannableStringBuilder();
        builder.append("进入系统即同意");

        String userAgreement = "《用户协议》";
        SpannableString userAgreementSpannable = new SpannableString(userAgreement);
        userAgreementSpannable.setSpan(new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
                //用户协议点击
            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                super.updateDrawState(ds);
                ds.setColor(Color.WHITE);
                ds.setUnderlineText(false);
            }
        }, 0, userAgreement.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

        builder.append(userAgreementSpannable);
        builder.append("和");
        String privacyPolicy = "《隐私政策》";
        SpannableString privacyPolicySpannable = new SpannableString(privacyPolicy);
        privacyPolicySpannable.setSpan(new ClickableSpan() {
            @Override
            public void onClick(@NonNull View widget) {
                //隐私政策点击

            }

            @Override
            public void updateDrawState(@NonNull TextPaint ds) {
                super.updateDrawState(ds);
                ds.setColor(Color.WHITE);
                ds.setUnderlineText(false);//取消下划线
            }
        }, 0, userAgreement.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        builder.append(privacyPolicySpannable);
        mArguementText.setMovementMethod(LinkMovementMethod.getInstance());
        mArguementText.setHighlightColor(getResources().getColor(android.R.color.transparent, null));
        mArguementText.setText(builder);
    }

 

其他Span

  上面的span只是一些常用的span演示,但是其实还有更多的span可以选择和使用,他们都在这个目录中.在这个目录下还有以下这些span.如果后续有时间我会一一实验使用这些span以判断他们的功能.

放弃富文本效果,提取文本

之前有端时间苦恼怎么提取不带富文本格式的文本,因为源代码的有很多方法并没有注释,所以蛋疼了很久..,后面突然发现,直接使用toString()方法就行

spannableString.toString()

 

END

SpannableStringBuilder
posted on 2019-07-22 18:47  观心静  阅读(4681)  评论(0编辑  收藏  举报