Spannable的用法

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

设计稿

想了很久,感觉用控件堆不太好弄,于是询问蕾哥后知道了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中的<li>标签的圆点效果
  18. DrawableMarginSpan 、IconMarginSpan 图片+Margin样式
  19. ImageSpan 图片样式,主要用于在文本中插入图片 聊天中的emoji表情显示用的就是这个
  20. MaskFilterSpan 文本滤镜 目前只有模糊效果和浮雕效果
  21. 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);
        }
    }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • ¥开启¥ 【iAPP实现进入界面执行逐一显】 〖2017-08-25 15:22:14〗 《//首先开一个线程,因...
    小菜c阅读 6,351评论 0 17
  • 使用下面两个类的setSpan()方法设置不同的样式Span来实现富文本: SpannableString - 实...
    shellever阅读 3,790评论 1 38
  • 《金丝雀》 你爱上金丝雀的鸣叫 关在笼里听到老 我爱上金丝雀的羽毛 看那天空有多高 囚禁的寂寞,谁知道? 你爱愈深...
    飞狐119阅读 434评论 4 2
  • 10:30醒来便开始缠绵,每天闭眼到醒来的吻习惯的太自然,代替了晚安、早安。 你一定不知道我有多享受你给的拥抱。 ...
    Ermao阅读 126评论 0 1
  • 今夜我不会遇见你,今夜我遇见了世上的一切,但不会遇见你。 ________题记 第一次见她...
    麦兜兜麦阅读 220评论 0 0