本文介绍一种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即可~如此便可大功告成。
思路还是很重要呀~