大家都知道,textView有一個setCompoundDrawables的方法來設置上下左右位置的圖標,當然,也可以在xml佈局文件中設置,然而問題來了,假如我們把圖標放在左邊,當我們讓TextView分多行顯示的時候,會出現一種情況,左邊的圖標並不會與第一行對齊,而是與整個textView居中對 ...
大家都知道,textView有一個setCompoundDrawables的方法來設置上下左右位置的圖標,當然,也可以在xml佈局文件中設置,然而問題來了,假如我們把圖標放在左邊,當我們讓TextView分多行顯示的時候,會出現一種情況,左邊的圖標並不會與第一行對齊,而是與整個textView居中對齊。
即我們要的是下圖:
結果是這個圖:
怎麼辦呢?我們可以用圖文混排:
我們可以利用SpannableString和ImageSpan。
1、構建SpannableString對象。
SpannableString spanString = new SpannableString(textView.getText().toString());
2、獲取Drawable對象,即將我們的圖案轉換為Drawable對象,並設置大小。
Drawable tvDrawable = ContextCompat.getDrawable(mContext, R.drawable.pic);
tvDrawable.setBounds(0, 0, tvDrawable.getMinimumWidth(), tvDrawable.getMinimumHeight());
3、構建ImageSpan 對象
ImageSpan span = new ImageSpan(tvDrawable, ImageSpan.ALIGN_BASELINE);
4、設置給上面的SpannableString對象
spanString.setSpan(span, 0, 1, Spannable.SPAN_INCLUSIVE_EXCLUSIVE);
5、最終設置給TextView
textView.setText(spanString)
加下來講講上面的方法:
1、ImageSpan對象,第二個參數為圖像與文字的對齊方式,ImageSpan只帶有兩個對齊方式,分別是:ALIGN_BASELINE、ALIGN_BOTTOM。
ALIGN_BOTTOM 表示與文字內容的底部對齊,如果在構造ImageSpan時沒有傳入對齊方式,那麼預設就是這種底部對齊。
ALIGN_BASELINE, 表示與文字內容的基線對齊
ImageSpan Span = new ImageSpan(tvDrawable, ImageSpan.ALIGN_BASELINE);
2、setSpan()方法
public void setSpan(Object what, int start, int end, int flags) {
super.setSpan(what, start, end, flags);
}
what傳入各種Span類型的實例;
start和end標記要替代的文字內容的範圍;
flags是用來標識在Span範圍內的文本前後輸入新的字元時是否把它們也應用這個效果,它有如下幾個:
Spanned.SPAN_EXCLUSIVE_EXCLUSIVE、
Spanned.SPAN_INCLUSIVE_EXCLUSIVE、
Spanned.SPAN_EXCLUSIVE_INCLUSIVE、
Spanned.SPAN_INCLUSIVE_INCLUSIVE
INCLUSIVE表示應用該效果,EXCLUSIVE表示不應用該效果,如Spanned.SPAN_INCLUSIVE_EXCLUSIVE表示對前面的文字應用該效果,而對後面的文字不應用該效果。
坑:
1、既然ImageSpan只帶有兩個對齊方式,那我們需要自己實現居中對齊:
class MyImageSpan extends ImageSpan {
public static final int ALIGN_CENTER = 2;
public MyImageSpan(Drawable d, int verticalAlignment) {
super(d, verticalAlignment);
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
Drawable b = getDrawable();
canvas.save();
Paint.FontMetricsInt fm = paint.getFontMetricsInt();
//系統預設為ALIGN_BOTTOM
int transY = bottom - b.getBounds().bottom;
if (mVerticalAlignment == ALIGN_BASELINE) {
transY -= fm.descent;
} else {
transY = ((y + fm.descent + y + fm.ascent) / 2
- b.getBounds().bottom / 2);
}
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}
@Override
public int getSize(Paint paint, CharSequence text, int start, int end, Paint.FontMetricsInt fm) {
Drawable b = getDrawable();
Rect rect = b.getBounds();
if (fm != null) {
Paint.FontMetricsInt painFm = paint.getFontMetricsInt();
int fontHeight = (painFm.bottom - painFm.top);
int drHeight = rect.bottom - rect.top;
int top = drHeight / 2 - fontHeight / 4;
int bottom = drHeight / 2 + fontHeight / 4;
fm.ascent = -bottom;
fm.top = -bottom;
fm.bottom = top;
fm.descent = top;
}
return rect.right;
}
}
為何上面的自定義能夠實現居中對齊呢?首先要瞭解Paint.FontMetrics。
請看另一篇博客:https://www.cnblogs.com/tangZH/p/8692910.html