之前寫過一篇圖文混排的,算法就是通過計算文本寬及行數,在換行的時候截取文本剩餘的部分顯示在圖片下邊,
代碼下載:demo
今天這邊是工作共常用到的,標籤在前或在最後顯示,比如帖子前邊顯示多個標籤表示精華帖、優秀帖、解決標籤等;其實主要是重寫DynamicDrawableSpan,以及通過設置SpanableStringBuilder,來顯示的。
先上圖
代碼如下:
主要是將普通文本替換成圖片文本之後(spannaableString)追加到文本後邊
/**
* 添加標籤
*
* @param tagIconPosition 將標籤放在文本的前面或者後邊
* @param tagDrawableIdList 本地標籤的drawableId集合
*/
private CharSequence addTagText(final int tagIconPosition, final List<Integer> tagDrawableIdList, CharSequence emojiText) {
if (tagDrawableIdList == null || tagDrawableIdList.size() == 0) {
return emojiText;
}
setText(emojiText);
SpannableStringBuilder spannableStringBuilder = new SpannableStringBuilder("");
for (int i = 0; i < tagDrawableIdList.size(); i++) {
spannableStringBuilder.append("t ");
}
for (int i = 0; i < tagDrawableIdList.size(); i++) {
int resourceId = tagDrawableIdList.get(i);
TagSpan tagSpanned = new TagSpan(context, resourceId, (int) getTextSize(), TagSpan.ALIGN_BASELINE, (int) getTextSize());
spannableStringBuilder.setSpan(tagSpanned, i * 2, i * 2 + 1, Spanned.SPAN_EXCLUSIVE_EXCLUSIVE);
}
CharSequence sepText = getText();
if (tagIconPosition == START) {//icon顯示在前面
spannableStringBuilder.append(sepText);
} else {
spannableStringBuilder.insert(0, sepText);
}
// setText(spannableStringBuilder);//最後設置
return spannableStringBuilder;
}
重寫DynamicDrawableSpan類,設置tag的位置,主要是因爲用原生的Span會有邊界錯位的問題,所以要重寫onDraw()
代碼如下:也不復雜,計算方式自己根據需要調整
public Drawable getDrawable() {
if (mDrawable == null) {
try {
mDrawable = mContext.getResources().getDrawable(mResourceId);
mHeight = mSize;
mWidth = mHeight * mDrawable.getIntrinsicWidth() / mDrawable.getIntrinsicHeight();
mTop = (mTextSize - mHeight) / 2;
// 設置邊界還是會導致錯位
mDrawable.setBounds(0, mTop, mWidth, mTop + mHeight);
} catch (Exception e) {
// swallow
}
}
return mDrawable;
}
@Override
public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) {
//super.draw(canvas, text, start, end, x, top, y, bottom, paint);
Drawable b = getCachedDrawable();
canvas.save();
int transY = bottom - b.getBounds().bottom;
if (mVerticalAlignment == ALIGN_BASELINE) {// 繪製圖片的位置
transY = top + ((bottom - top) / 2) - ((b.getBounds().bottom - b.getBounds().top) / 2) - mTop;
}
// 由於圖片會錯位,所以要移動這個畫布
canvas.translate(x, transY);
b.draw(canvas);
canvas.restore();
}
現在說另一種實現方式:不過就是因爲這種實現方式有錯位問題,才使用方式一的,但是有些情況不需要自定義DynamicDrawableSpan就可以插入文本的,多學點無壞處吧,一併寫下來說不定以後對自己有幫助
實現方式是通過Html.fromHtml( text,imageGetter);實現的;
代碼如下:
1 、實現一個html轉化時需要的imageGetter,主要用於識別html 帶有<img src="">的標籤
/**
* 注:在異步線程中:先將文本表情轉換成charsequence,然後加載icon,再者將icon放在文本表情的前或後,最後通過handler在主線程中設置textview 下午8:47:02 Spanned
*/
private Spanned convertTagToIconSpanned(CharSequence emojiText, int tagIconPosition, List<Integer> tagDrawablIds) {
StringBuilder temp = new StringBuilder();
for (int i : tagDrawablIds) {//先將drawId轉成html標籤,
temp.append("<img src='" + i + "'/> ");
}
Spanned tagSpanned = Html.fromHtml(temp.toString(), getImageGetterInstance(), null);
if (tagIconPosition == START) {// 本地圖片放在文本前邊
SpannableStringBuilder span = new SpannableStringBuilder(tagSpanned);
span.append(emojiText);
return span;
} else if (tagIconPosition == END) {// 本地圖片放在文本後邊
SpannableStringBuilder span = new SpannableStringBuilder(emojiText);
span.append(tagSpanned);
return span;
}
return new SpannableStringBuilder(emojiText);
}
2、獲取標籤的圖片
/**
* ImageGetter用於text圖文混排
*
* @return
*/
public ImageGetter getImageGetterInstance() {
ImageGetter imgGetter = new ImageGetter() {
@Override
public Drawable getDrawable(String source) {// 可用於加載本地圖片和網絡圖片,source就是標籤設置的<img src=""> src的值
int fontH = (int) (getTextSize());
int id = Integer.parseInt(source);
Drawable d = drawableMap.get(id);
if (d == null) {
d = getResources().getDrawable(id);
drawableMap.put(id, d);
}
int height = fontH;
int width = (int) ((float) d.getIntrinsicWidth() / (float) d.getIntrinsicHeight()) * fontH;
if (width == 0) {
width = d.getIntrinsicWidth();
}
d.setBounds(0, 0, width, height);
return d;
}
};
return imgGetter;
}
3,通過html轉化成 Spanned ;用於setText(),就完成設置了
Spanned tagSpanned = Html.fromHtml(temp.toString(), getImageGetterInstance(), null);
希望對你有一點幫助