如何给你的 Android App 添加自定义表情

上一篇文章 Android Span 原理解析 介绍了 Span 的原理。这一篇文章将介绍 Span 的应用,使用 Span 来给 App 添加自定义表情。

原理

添加自定义表情的原理其实很简单,就是使用 ImageSpan 对文字进行替换。代码如下:

ImageSpan imageSpan = new ImageSpan(this, R.drawable.emoji_kelian);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("哈哈哈哈[可怜]");
spannableStringBuilder.setSpan(imageSpan, 4, spannableStringBuilder.length(), Spannable.SPAN_EXCLUSIVE_EXCLUSIVE);
textView.setText(spannableStringBuilder);

上面的代码把 [可怜] 文字替换成了对应的表情图片。效果如下图,可以看到图片的大小不符合预期,这是因为 ImageSpan 会显示成图片原来的大小。

在这里插入图片描述
ImageSpan 的继承关系图如下,出现了 ReplacementSpanDynamicDrawableSpan 两个新的类,先来看一下它们。MetricAffectingSpanCharacterStyle 接口在 Android Span 原理解析 介绍了,这里就不赘述了。
在这里插入图片描述

ReplacementSpan 接口

ReplacementSpan 是一个接口,看名字是用来替换文字的。它里面定义了两个方法,如下所示。

public abstract int getSize(@NonNull Paint paint, 
                        CharSequence text,
                        @IntRange(from = 0) int start, 
                        @IntRange(from = 0) int end,
                        @Nullable Paint.FontMetricsInt fm);

返回替换后 Span 的宽,上面的例子中就是返回图片的宽度,参数作用如下:

  • paint: Paint 的实例
  • text: 当前文本,上面的例子中它的值是是 哈哈哈哈[可怜]
  • start: Span 的开始位置,这里是 4
  • end: Span 的结束位置,这里是 8
  • fm: FontMetricsInt 的实例

FontMetricsInt 是描述给定文本大小的字体的各种度量的类。内部属性代表的含义如下图:

  • Top:图中紫线的位置
  • Ascent: 图中绿线的位置
  • Descent: 图中蓝线的位置
  • Bottom: 图中黄线的位置
  • Leading: 未在图中标出,是指上一行的 Bottom 与下一行的 Top 之间的距离。

图片来源 Meaning of top, ascent, baseline, descent, bottom, and leading in Android’s FontMetrics
在这里插入图片描述

Baseline 是文字绘制的基准线。它不定义在 FontMetricsInt 中,但可以通过 FontMetricsInt 的属性获取。

上面讲到 getSize 方法只返回宽度,那高度是怎么确定的呢?其实它是通过 FontMetricsInt 来控制,不过这里有个坑,后面会说到。

public abstract void draw(@NonNull Canvas canvas, 
                        CharSequence text,
                          @Int
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值