专栏首页lzj_learn_noteAndroid ImageSpan与TextView同一行图片居中

Android ImageSpan与TextView同一行图片居中

在开发中常常会遇到标签(图片)+文字的需求,实现方式一般采用SpannableString的方式来实现。 这时候会遇到图片ImageSpan没有办法居中的问题。在解决这个问题之前,先学习字体属性Paint.FontMetrics。

图片1

图片2

通过上面的示意图,再看下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

在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) 参数解析:

  • x:要绘制的image的左边框到textview左边框的距离。
  • y:替换文字的基线坐标。
  • top:替换改行文字的最顶部位置。
  • 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();
    }
  • y +fontMetricsInt.descent得到字体的descent线坐标
  • y + fontMetricsInt.ascent得到字体的ascent线坐标
  • 两者相加除以2,得到改行文字的中线坐标
  • drawable.getBounds().bottom/2得到图片中线坐标
  • 然后两者相减,即可获得图片需要移动多长的距离可以居中
  • 最后将相减得到的距离传给canvas.translate(x,transY)即可

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • RecyclerView的一些开源LayoutManager

    Google默认为RecyclerView提供了LinearLayoutManager、StaggeredGridLayoutManager、GridLayou...

    用户3106371
  • 5-遍历、公共方法、引用

    通过for ... in ...:的语法结构,可以遍历字符串、列表、元组、字典,集合等数据结构。

    用户3106371
  • Android TextView实现查看全部和收起功能

    在工作遇到上图所示的一个小需求,将“查看全部”的提示连在原文的后面,使用一个textview显示。实现该功能大致步骤:

    用户3106371
  • Collections的singleton,singletonList,singletonMap

    这里只需要创建一个元素的List的时候用Arrays.asList()的话那插件就会在代码下报黄线提示你这是代码坏味道,建议优化。后面我就发现了使用Collec...

    爱敲代码的猫
  • LeetCode 231. Power of Two

    ShenduCC
  • AsyncListDiffer-RecyclerView最好的伙伴

    导读,近些年来 Android 一直在优化 RecyclerView 刷新效率,相继出了 DiffUtil,AsyncListDiffer ,我在我的开源库 F...

    程序亦非猿
  • Android AIDL 传递对象(Parceable)

    版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/gdutxiaoxu/article/de...

    用户2965908
  • java redis 通用组建

    前言 redis 是个干嘛的 ? 看官网:http://redis.io/ 一句话,这里redis当做缓存(或者本来就是), 利用java写一个jedis的读...

    一灰灰blog
  • Uber 开源「神经演化」可视化工具 VINE

    AI 研习社前段时间曾对 Uber 数日连发的 5 篇关于神经演化的文章进行了深度的解读。这些文章介绍了他们在遗传算法(genetic algorithm)、突...

    AI研习社
  • 动态 | Uber开源「神经演化」可视化工具VINE

    AI 科技评论按:算力的提升可能会为旧的算法注入活力。近两年来,神经演化(Neuroevolution)的方法逐渐再次受到关注,包括 OpenAI、DeepMi...

    AI科技评论

扫码关注云+社区

领取腾讯云代金券