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


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