最近項目中需要實現一個評論帶表情的功能,剛開始一切順利,非常easy,突然有一天發現文字跟表情混排的時候,TextView中圖文高度不一致,excuse。。。什么鬼,之前明明測試過圖文混排,不存在這個問題啊,然后檢查代碼,沒毛病啊,
android:gravity="center_vertical" 也設置了啊,然后猛然發現一行代碼:android:lineSpacingExtra="8sp",原來是設置了這個行間距導致的。知道問題出在哪了,就好解決了,度娘還是看源碼,都OK的啊。
先貼一下對比圖
解決之前的效果圖:
解決之后的效果圖:

圖文混排,不可缺少:SpannableString和ImageSpan,但是閱讀源碼發現,ImageSpan設置對齊方式只有兩種:
/** * A constant indicating that the bottom of this span should be aligned * with the bottom of the surrounding text, i.e., at the same level as the * lowest descender in the text. */ public static final int ALIGN_BOTTOM = 0; /** * A constant indicating that the bottom of this span should be aligned * with the baseline of the surrounding text. */ public static final int ALIGN_BASELINE = 1;
要是ImageSpan能提供一個使其內容垂直居中的,問題不就輕松解決了嗎,但是它沒有提供了,****,再看,源碼
ImageSpan是繼承DynamicDrawableSpan的,而DynamicDrawableSpan中有兩個這樣的方法:getSize和draw,
@Override public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) { Drawable d = getCachedDrawable(); Rect rect = d.getBounds(); if (fm != null) { fm.ascent = -rect.bottom; fm.descent = 0; fm.top = fm.ascent; fm.bottom = 0; } return rect.right; }
@Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { Drawable b = getCachedDrawable(); canvas.save(); int transY = bottom - b.getBounds().bottom; if (mVerticalAlignment == ALIGN_BASELINE) { transY -= paint.getFontMetricsInt().descent; } canvas.translate(x, transY); b.draw(canvas); canvas.restore(); }
所以我們也可以自定義去實現,最后貼上代碼:
import android.content.Context; import android.graphics.Bitmap; import android.graphics.Canvas; import android.graphics.Paint; import android.graphics.Rect; import android.graphics.drawable.Drawable; import android.text.style.ImageSpan; import java.lang.ref.WeakReference; /** * @Created SiberiaDante * @Describe: * @Time: 2017/8/18 * @Email: 994537867@qq.com * @GitHub: https://github.com/SiberiaDante */ public class CenterAlignImageSpan extends ImageSpan { private WeakReference<Drawable> mDrawableRef; public CenterAlignImageSpan(Context context, Bitmap bitmap, int verticalAlignment) { super(context, bitmap, verticalAlignment); } public CenterAlignImageSpan(Context context, int resId, int verticalAlignment) { super(context, resId, verticalAlignment); } @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; } @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { Drawable drawable = getCachedDrawable(); 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(); } private Drawable getCachedDrawable() { WeakReference<Drawable> wr = mDrawableRef; Drawable d = null; if (wr != null) { d = wr.get(); } if (d == null) { d = getDrawable(); mDrawableRef = new WeakReference<>(d); } return d; } }
最后:
SpannableString spannableStringCustom = new SpannableString("測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排測試圖文混排"); CenterAlignImageSpan span = new CenterAlignImageSpan(this, R.mipmap.ic_launcher, ImageSpan.ALIGN_BASELINE);//重寫的ImageSpan spannableStringCustom.setSpan(span, 0, 2, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE); textViewCustom.setText(spannableStringCustom);
參考文章:https://segmentfault.com/a/1190000007133405
