android之文本前面或後面多標籤

之前寫過一篇圖文混排的,算法就是通過計算文本寬及行數,在換行的時候截取文本剩餘的部分顯示在圖片下邊,

代碼下載: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);

希望對你有一點幫助

多標籤Demo


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章