Spannable的用法

今天碰到了一个问题,为一段文字添加双引号,使得文字包裹在双引号内。设计稿如下:

Spannable的用法_第1张图片
设计稿

想了很久,感觉用控件堆不太好弄,于是询问蕾哥后知道了Spannable这个类。然后在网上查了查这个类的用法,发现用这个类就是用来实现文本的样式修改。
Spannable继承自Spanned接口,而实际上,Spanned继承自CharSequence接口。
在TextView的 setText(CharSequence text)方法中,要求的参数正好是一个CharSequence对象,因此,我们可以通过Spannable对象来直接使用setText来完成文本的设置。在使用中通常使用 Spannable spn = new SpannableString("字符串");或者通过SpannableStringBuilder对象来进行构建。
在构建除了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]

第一个参数传入一个样式,样式种类有,具体参见这里和这里:

  1. AbsoluteSizeSpan 指定文字大小
  1. TypefaceSpan 可以设置不同的字体
  2. AlignmentSpan.Standard 标准文本对齐
  3. BackgroundColorSpan 文本背景颜色
  4. ForegroundColorSpan 文字字体颜色
  5. LeadingMarginSpan 文本缩进
  6. TabStopSpan 制表位偏移样式
  7. TextAppearanceSpan 使用style文件来定义文本样式
  8. RelativeSizeSpan 对于文本设定的大小的相对比例
  9. ScaleXSpan 将字体按比例进行横向缩放
  10. URLSpan 可以打开一个链接
  11. StyleSpan 正常粗体斜体同时加粗倾斜四种样式
  12. StrikethroughSpan 删除线样式
  13. QuoteSpan 在文本左侧添加一条表示引用的竖线
  14. UnderlineSpan 给一段文字加上下划线
  15. SubscriptSpan 脚注样式,比如化学式的常见写法
  16. SuperscriptSpan 上标样式,比如数学上的次方运算
  17. BulletSpan 文本着重样式,类似于HTML中的
  18. 标签的圆点效果
  19. DrawableMarginSpan 、IconMarginSpan 图片+Margin样式
  20. ImageSpan 图片样式,主要用于在文本中插入图片 聊天中的emoji表情显示用的就是这个
  21. MaskFilterSpan 文本滤镜 目前只有模糊效果和浮雕效果
  22. RasterizerSpan 光栅化

通过这种方式,我实现最上面的需求,实现方法如下:

public static SpannableStringBuilder addQuoteSpannableStr(String resoneStr){
    SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("“" + resoneStr + "”");
    int length = spannableStringBuilder.length();

    spannableStringBuilder.setSpan(new AbsoluteSizeSpan(DensityUtil.dip2px(17)), 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new AbsoluteSizeSpan(DensityUtil.dip2px(15)), 1, length - 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new AbsoluteSizeSpan(DensityUtil.dip2px(17)), length - 1, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);

    spannableStringBuilder.setSpan(new ForegroundColorSpan(ResourceUtil.getColor(R.color.ab_life_feed_item_recommend_quote)), 0, 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new ForegroundColorSpan(ResourceUtil.getColor(R.color.ab_life_feed_item_recommend_resone)), 1, length - 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    spannableStringBuilder.setSpan(new ForegroundColorSpan(ResourceUtil.getColor(R.color.ab_life_feed_item_recommend_quote)), length - 1, length, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
    return spannableStringBuilder;
}

最后再附录一段添加emoji代码:

 public static void convert2RichText(String text, Spannable spannable, float scaleRate) {
    Pattern pattern = Pattern.compile("\\[([0-9]+)\\]");
    Matcher matcher = pattern.matcher(text);
    while (matcher.find()) {
        String emojiId = matcher.group(1);
        System.out.println("emojiId:" + emojiId);
        if (EMOJI_MAP.containsKey(emojiId)) {
            Drawable drawable = getEmojiDrawable(context, emojiId, scaleRate);
            int imageStartIndex = matcher.start();
            int imageEndIndex = matcher.end();
            ImageSpan span = new ImageSpan(drawable, ImageSpan.ALIGN_BOTTOM);
            spannable.setSpan(span, imageStartIndex, imageEndIndex, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
        }
    }
}

你可能感兴趣的:(Spannable的用法)