美文网首页程序员
Android ImageSpan与TextView同一行图片居

Android ImageSpan与TextView同一行图片居

作者: time_fly | 来源:发表于2017-05-26 18:51 被阅读1807次

    在开发中常常会遇到标签(图片)+文字的需求,实现方式一般采用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)即可

    相关文章

      网友评论

        本文标题:Android ImageSpan与TextView同一行图片居

        本文链接:https://www.haomeiwen.com/subject/yhyxfxtx.html