項目中有如題的需求:
網上看了好多也都有些問題。最終找到正確方法,如下:
1.要生成一個拼接的動態圖片的Bitmap。這裏的思路是將佈局轉換成Bitmap,這個佈局可以是通過LayoutInflater.inflate得來的,也可以是直接在Activity 或者fragment的佈局中顯示出來的。如下便是生成bitmap的工具方法。經實驗有效:
public synchronized static Bitmap getBitmapFrom(View contentView) { Bitmap bit = null; try { contentView.setLayoutParams(new ViewGroup.LayoutParams(RelativeLayout.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)); contentView.setDrawingCacheEnabled(true); contentView.measure(View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED), View.MeasureSpec.makeMeasureSpec(0, View.MeasureSpec.UNSPECIFIED)); contentView.layout(0, 0, contentView.getMeasuredWidth(), contentView.getMeasuredHeight()); contentView.buildDrawingCache(); bit = contentView.getDrawingCache(); if (bit == null) { contentView.setDrawingCacheEnabled(true); bit = Bitmap.createBitmap(contentView.getWidth(), contentView.getHeight(), Bitmap.Config.ARGB_8888); Canvas c = new Canvas(bit); c.translate(-contentView.getScrollX(), -contentView.getScrollY()); contentView.draw(c); return bit; } } catch (Exception e) { e.printStackTrace(); } return bit; }
2.要在TextView 末尾拼接圖片,那就可以用到ImageSpan,如下:
public class VerticalImageSpan extends ImageSpan { public VerticalImageSpan(Drawable drawable) { super(drawable); } public VerticalImageSpan(Drawable d, String source) { super(d, source); } public VerticalImageSpan(Context context, int resourceId) { super(context, resourceId); } /** * update the text line height */ @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; } /** * see detail message in android.text.TextLine * * @param canvas the canvas, can be null if not rendering * @param text the text to be draw * @param start the text start position * @param end the text end position * @param x the edge of the replacement closest to the leading margin * @param top the top of the line * @param y the baseline * @param bottom the bottom of the line * @param paint the work paint */ @Override public void draw(Canvas canvas, CharSequence text, int start, int end, float x, int top, int y, int bottom, Paint paint) { Drawable drawable = getDrawable(); 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(); } }
3.因爲是動態生成的圖片,所以用ImageSpan 拼接的時候也是需要動態的獲取drawable 的寬高的,那麼我們便可以在Activity 或者Fragment 中爲一個TextView aTextView 設置相同的文本(因爲只有佈局加載出來才能拿到寬高),通過監聽TextView 的繪製完成方法,來拿到aTextView的寬高,進而給drawable 設置寬高,如下:
Drawable drawable = new BitmapDrawable(null, bitmap); //mTvPeroid 是設置的顯示在Activity 中的TextView 但是我們看不見,通過mTvPeroid 來拿到寬高。 ViewTreeObserver observer = mTvPeroid.getViewTreeObserver(); observer.addOnGlobalLayoutListener(new ViewTreeObserver.OnGlobalLayoutListener() { @Override public void onGlobalLayout() { mTvPeroid.getViewTreeObserver().removeOnGlobalLayoutListener(this); int height = mTvPeroid.getHeight(); int width = mTvPeroid.getWidth(); //這一步很重要,沒有這一步,圖片就無法正常顯示。 drawable.setBounds(0, 0, width, height); VerticalImageSpan span = new VerticalImageSpan(drawable); SpannableString ss = new SpannableString(" "); ss.setSpan(span, 0, ss.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); //拼接圖片 mTvGroupName.append(" "); mTvGroupName.append(ss); } });
這樣三步就可以滿足需求了。