[Android]ImageSpan与TextView同一行图片居中

在开发中常常会遇到标签(图片)+文字的需求,实现方式一般采用SpannableString的方式来实现。 这时候会遇到图片ImageSpan没有办法居中的问题。在解决这个问题之前,先学习字体属性Paint.FontMetrics。
文字实际尺寸属性
文字实际位置属性
通过上面的示意图,再看下FontMetrics 类:

 public static class FontMetrics {
    /**
     * The maximum distance above the baseline for the tallest glyph in
     * the font at a given text size.
     */
    public float   top;//最高字符到baseline的值,即ascent的最大值
    /**
     * The recommended distance above the baseline for singled spaced text.
     */
    public float   ascent;//系统建议的,绘制单个字符时,baseline至字符最高处的距离
    /**
     * The recommended distance below the baseline for singled spaced text.
     */
    public float   descent;//系统建议的,绘制单个字符时,baseline至字符最低处的距离
    /**
     * The maximum distance below the baseline for the lowest glyph in
     * the font at a given text size.
     */
    public float   bottom;//最低字符到baseline的值
    /**
     * The recommended additional space to add between lines of text.
     */
    public float   leading;//上一行字符的descent到下一行字符ascent之间的距离,行间距
}
  • ascent线Y坐标 = baseline线的y坐标 + fontMetric.ascent;
  • descent线Y坐标 = baseline线的y坐标 + fontMetric.descent;
  • top线Y坐标 = baseline线的y坐标 + fontMetric.top;
  • bottom线Y坐标 = baseline线的y坐标 + fontMetric.bottom;

在ImageSpan的构造函数中有一个对齐方式的参数,但只提供了

ALIGN_BASELINE(顶部对齐)、ALIGN_BOTTOM (底部对齐)

两种对齐方式,没有居中对齐的方式, 所以只能重写ImageSpan实现图片的居中。

public void draw(Canvas canvas, CharSequence text,int start, int end,
float x, int top, int y, int bottom, Paint paint)

参数解析:

  1. x:要绘制的image的左边框到textview左边框的距离。
  2. y:替换文字的基线坐标。
  3. top:替换改行文字的最顶部位置。
  4. bottom:替换改行文字的最底部位置,行间距属于上一行,因而bottom是行间距的底部位置。

然后重写draw()方法即可实现图片居中,实现方式如下:

 @Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
    Drawable drawable = getDrawable();
    Paint.FontMetricsInt fontMetricsInt = paint.getFontMetricsInt();
    int transY = (y + fontMetricsInt.descent + y + fontMetricsInt.ascent) / 2 - drawable.getBounds().bottom/2;
    canvas.save();
    canvas.translate(x,transY);
    drawable.draw(canvas);
    canvas.restore();
}
  1. y +fontMetricsInt.descent得到字体的descent线坐标
  2. y + fontMetricsInt.ascent得到字体的ascent线坐标
  3. 两者相加除以2,得到该行文字的中线坐标
  4. drawable.getBounds().bottom/2得到图片中线坐标
  5. 然后两者相减,即可获得图片需要移动多长的距离可以居中
  6. 最后将相减得到的距离传给canvas.translate(x,transY)即可
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值