android 图文混排

本文介绍一种Android中简单的图文混排方式

首先,大家先看下UI给的效果图:

首先我们可以大致简单的分析一下该需求,第一眼看起来,可能会突然想说简单的使用用ImageView + Textview就可以直接实现了,没什么麻烦的地方,但其实不然,因为提示后边的文字是自动换行的,即图片和文字是一体的,且可以在任意位置换行。

这样的展示效果当然可以使用自定义控件来实现,但杀鸡焉用牛刀,我们可以使用TextView的特性来轻松的实现该功能。

话不多说,直接上代码吧(里边使用到的类都可以在javadoc中查到)


        //声明一个字符串,预留一个图片的位置“iamge”
        String content = "image" + " 想看看大家在直播中都" + "\n" + "说了什么?点击这里";
        //将content 包装成 SpannableString 
        SpannableString ss = new SpannableString(content);
        //使用ForegroundColorSpan定义需要改变的字体的前景色颜色值及位置
        ss.setSpan(new ForegroundColorSpan(Color.parseColor("#5182b3")), content.length() - 4, content.length(), Spannable.SPAN_INCLUSIVE_INCLUSIVE);
        //得到提示图片对象
        Drawable drawable = context.getResources().getDrawable(R.drawable.icon_tip);
        //将image 这个字符串替换成 我们需要的图片
        drawable.setBounds(0, 0, d.getIntrinsicWidth(), d.getIntrinsicHeight());
        ImageSpan span = new ImageSpan(d);
        ss.setSpan(span, 0, "image".length(), Spannable.SPAN_INCLUSIVE_EXCLUSIVE); 
        //将ss设置到textView中       
textView.append(ss);

    通过该方式可以简单的实现上图UI效果,但是如果文本只有一行,将会出现图片不上下居中的问题。

    此时我们需要写一个工具类

public class VerticalImageSpan extends ImageSpan {

    public VerticalImageSpan(Drawable drawable) {
        super(drawable);
    }

    /**
     * update the text line height
     */
    @Override
    public int getSize(Paint paint, CharSequence text, int start, int end,
                       Paint.FontMetricsInt fontMetricsInt) {
        Drawable drawable = getDrawable();
        Rect rect = drawable.getBounds();
        if (fontMetricsInt != null) {
            Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
            int fontHeight = fmPaint.descent - fmPaint.ascent;
            int drHeight = rect.bottom - rect.top;
            int centerY = fmPaint.ascent + fontHeight / 2;

            fontMetricsInt.ascent = centerY - drHeight / 2;
            fontMetricsInt.top = fontMetricsInt.ascent;
            fontMetricsInt.bottom = centerY + drHeight / 2;
            fontMetricsInt.descent = fontMetricsInt.bottom;
        }
        return rect.right;
    }

    /**
     * see detail message in android.text.TextLine
     *
     * @param canvas the canvas, can be null if not rendering
     * @param text the text to be draw
     * @param start the text start position
     * @param end the text end position
     * @param x the edge of the replacement closest to the leading margin
     * @param top the top of the line
     * @param y the baseline
     * @param bottom the bottom of the line
     * @param paint the work paint
     */
    @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();
        canvas.save();
        Paint.FontMetricsInt fmPaint = paint.getFontMetricsInt();
        int fontHeight = fmPaint.descent - fmPaint.ascent;
        int centerY = y + fmPaint.descent - fontHeight / 2;
        int transY = centerY - (drawable.getBounds().bottom - drawable.getBounds().top) / 2;
        canvas.translate(x, transY);
        drawable.draw(canvas);
        canvas.restore();
    }
}

只要将第一段代码中的ImageSpan换成我们新鞋的 VerticalImageSpan即可~如此便可大功告成。

思路还是很重要呀~

猜你喜欢

转载自blog.csdn.net/qq564045867/article/details/80325854