Spannable的使用(文本样式设置)

通过Spannable对象我们可以设置textview的各种样式

用法

setSpan(Object what, int start, int end, int flags)

1. 第一个参数

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

2. 第四个参数 

Flags    意思    符号
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]

3. 自定义圆角背景

package com.ypf.study.myroom;

import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.text.style.ReplacementSpan;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;

public class RoundBackgroundColorSpan extends ReplacementSpan {
    private int bgColor;
    private int textColor;

    public RoundBackgroundColorSpan(int bgColor, int textColor) {
        super();
        this.bgColor = bgColor;
        this.textColor = textColor;
    }

    @Override
    public void draw(@NonNull Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, @NonNull Paint paint) {
        int originalColor = paint.getColor();
        paint.setColor(this.bgColor);
        //画圆角矩形背景
        canvas.drawRoundRect(new RectF(x,
                        top + 1,
                        x + ((int) paint.measureText(text, start, end) + dp2px(10)),
                        bottom - 1),
                dp2px(4),
                dp2px(4),
                paint);
        paint.setColor(this.textColor);
        //画文字,两边各增加8dp
        canvas.drawText(text, start, end, x + dp2px(5), y, paint);
        //将paint复原
        paint.setColor(originalColor);
    }

    @Override
    public int getSize(@NonNull Paint paint, CharSequence text, int start, int end, @Nullable Paint.FontMetricsInt fm) {
        //设置宽度为文字宽度加16dp
        return ((int) paint.measureText(text, start, end) + dp2px(10));
    }
    private int dp2px(int dp) {
        return 5 * dp;
    }
}

4. 简单实用

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.test_span);
        String text = " # 影综创作者激励计划   # 我的快乐源泉   # 追剧   # 聚会开心时刻   # 青春不毕业  闺蜜模范,谁身边不想要一个这样的姐妹";
        SpannableStringBuilder builder = new SpannableStringBuilder(text);
        Matcher m = LABEL_PATTERN.matcher(builder);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            if (end - start == 1) {
                continue;
            }
            builder.setSpan(new AbsoluteSizeSpan(15), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        }
        builder = new SpannableStringBuilder(builder);
        m = LABEL_PATTERN.matcher(builder);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            if (end - start == 1) {
                continue;
            }
            builder.setSpan(new RoundBackgroundColorSpan(Color.GRAY, Color.BLACK), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        }
        textView.setText(builder);
    }

效果

5. bug场景

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        textView = findViewById(R.id.test_span);
        String text = " # 影综创作者激励计划   # 我的快乐源泉   # 追剧   # 聚会开心时刻   # 青春不毕业  闺蜜模范,谁身边不想要一个这样的姐妹 # 青春不毕业 ";
        SpannableStringBuilder builder = new SpannableStringBuilder(text);

        Matcher m = LABEL_PATTERN.matcher(builder);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            if (end - start <= 1) {
                continue;
            }
            builder.setSpan(new AbsoluteSizeSpan(dp2px(4)), start,
                    start + 1, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            builder.setSpan(new AbsoluteSizeSpan(dp2px(4)),
                    start + 2, start + 3, Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
            builder.setSpan(new AbsoluteSizeSpan(dp2px(4)), end - 1, end,
                    Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        }
        textView.setText(builder);

        m = LABEL_PATTERN.matcher(builder);
        while (m.find()) {
            int start = m.start();
            int end = m.end();
            if (end - start <= 1) {
                continue;
            }
            builder.setSpan(new RoundBackgroundColorSpan(Color.GRAY, Color.BLACK), start, end, Spanned.SPAN_INCLUSIVE_INCLUSIVE);
        }
        textView.setText(builder);
    }

    private int dp2px(int dp) {
        return 5 * dp;
    }

效果

修复方案

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值