文档章节

Android自定义View 实现图文混排

SuShine
 SuShine
发布于 2015/06/24 13:55
字数 740
阅读 43
收藏 0
package com.su.imagetextview;

import java.util.ArrayList;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.graphics.Paint.FontMetrics;
import android.util.AttributeSet;
import android.util.DisplayMetrics;
import android.view.View;


public class FloatImageText extends View {
	private Bitmap mBitmap;
	private final Rect bitmapFrame = new Rect();
	private final Rect tmp = new Rect();
	private int mTargetDentity = DisplayMetrics.DENSITY_DEFAULT;

	private final Paint mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);
	private String mText;
	private ArrayList<TextLine> mTextLines;
	private final int[] textSize = new int[2];

	public FloatImageText(Context context, AttributeSet attrs, int defStyle) {
		super(context, attrs, defStyle);
		init();
	}

	public FloatImageText(Context context, AttributeSet attrs) {
		super(context, attrs);
		init();
	}

	public FloatImageText(Context context) {
		super(context);
		init();
	}

	private void init() {
		mTargetDentity = getResources().getDisplayMetrics().densityDpi;
		mTextLines = new ArrayList<TextLine>();

		mPaint.setTextSize(30);
		mPaint.setColor(Color.RED);

	}

	@Override
	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
		int w = 0, h = 0;
		// 图像巨细
		w += bitmapFrame.width();
		h += bitmapFrame.height();

		// 文本宽度
		if (null != mText && mText.length() > 0) {
			mTextLines.clear();
			int size = resolveSize(Integer.MAX_VALUE, widthMeasureSpec);
			measureAndSplitText(mPaint, mText, size);
			final int textWidth = textSize[0], textHeight = textSize[1];
			w += textWidth; // 内容宽度
			if (h < textHeight) { // 内容高度
				h = (int) textHeight;
			}
		}

		w = Math.max(w, getSuggestedMinimumWidth());
		h = Math.max(h, getSuggestedMinimumHeight());

		setMeasuredDimension(resolveSize(w, widthMeasureSpec),
				resolveSize(h, heightMeasureSpec));
	}

	@Override
	protected void onDraw(Canvas canvas) {
		// 绘制图像
		if (null != mBitmap) {
			canvas.drawBitmap(mBitmap, null, bitmapFrame, null);
		}

		// 绘制文本
		TextLine line;
		final int size = mTextLines.size();
		for (int i = 0; i < size; i++) {
			line = mTextLines.get(i);
			canvas.drawText(line.text, line.x, line.y, mPaint);
		}
		System.out.println(mTextLines);
	}

	public void setImageBitmap(Bitmap bm) {
		setImageBitmap(bm, null);
	}

	public void setImageBitmap(Bitmap bm, int left, int top) {
		setImageBitmap(bm, new Rect(left, top, 0, 0));
	}

	public void setImageBitmap(Bitmap bm, Rect bitmapFrame) {
		mBitmap = bm;
		computeBitmapSize(bitmapFrame);
		requestLayout();
		invalidate();
	}

	public void setText(String text) {
		mText = text;
		requestLayout();
		invalidate();
	}

	private void computeBitmapSize(Rect rect) {
		if (null != rect) {
			bitmapFrame.set(rect);
		}
		if (null != mBitmap) {
			if (rect.right == 0 && rect.bottom == 0) {
				final Rect r = bitmapFrame;
				r.set(r.left, r.top,
						r.left + mBitmap.getScaledHeight(mTargetDentity), r.top
								+ mBitmap.getScaledHeight(mTargetDentity));
			}
		} else {
			bitmapFrame.setEmpty();
		}
	}

	private void measureAndSplitText(Paint p, String content, int maxWidth) {
		FontMetrics fm = mPaint.getFontMetrics();
		final int lineHeight = (int) (fm.bottom - fm.top);

		final Rect r = new Rect(bitmapFrame);
		// r.inset(-5, -5);

		final int length = content.length();
		int start = 0, end = 0, offsetX = 0, offsetY = 0;
		int availWidth = maxWidth;
		TextLine line;
		boolean onFirst = true;
		boolean newLine = true;
		while (start < length) {
			end++;
			if (end == length) { // 残剩的不足一行的文本
				if (start <= length - 1) {
					if (newLine)
						offsetY += lineHeight;
					line = new TextLine();
					line.text = content.substring(start, end - 1);
					line.x = offsetX;
					line.y = offsetY;
					mTextLines.add(line);
				}
				break;
			}
			p.getTextBounds(content, start, end, tmp);
			if (onFirst) { // 确定每个字符串的坐标
				onFirst = false;
				final int height = lineHeight + offsetY;
				if (r.top >= height) { // 顶部可以放下一行文字
					offsetX = 0;
					availWidth = maxWidth;
					newLine = true;
				} else if (newLine
						&& (r.bottom >= height && r.left >= tmp.width())) { // 中部左边可以放文字
					offsetX = 0;
					availWidth = r.left;
					newLine = false;
				} else if (r.bottom >= height
						&& maxWidth - r.right >= tmp.width()) { // 中部右边
					offsetX = r.right;
					availWidth = maxWidth - r.right;
					newLine = true;
				} else { // 底部
					offsetX = 0;
					availWidth = maxWidth;
					if (offsetY < r.bottom)
						offsetY = r.bottom;
					newLine = true;
				}
			}

			if (tmp.width() > availWidth) { // 保留一行能放置的最大字符串
				onFirst = true;
				line = new TextLine();
				line.text = content.substring(start, end - 1);
				line.x = offsetX;
				mTextLines.add(line);
				if (newLine) {
					offsetY += lineHeight;
					line.y = offsetY;
				} else {
					line.y = offsetY + lineHeight;
				}

				start = end - 1;
			}
		}
		textSize[1] = offsetY;
	}

	class TextLine {
		String text;
		int x;
		int y;

		@Override
		public String toString() {
			return "TextLine [text=" + text + ", x=" + x + ", y=" + y + "]";
		}
	}
}


package com.su.imagetextview;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.Menu;

public class MainActivity extends Activity {

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		FloatImageText view = new FloatImageText(this);

		view.setText("电视里发生了房间里是积分拉萨积分拉萨积分拉萨减肥啦空间  撒旦法发大水发撒旦法看完了鸡肉味容积率为热键礼物i经二路文件容量为积分拉萨解放路口上飞机撒离开房间爱水立方法拉圣诞节福禄寿");
		Bitmap bm = BitmapFactory.decodeResource(getResources(),
				R.drawable.ic_launcher);
		view.setImageBitmap(bm, 480 - bm.getWidth(),15);

		setContentView(view);
	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// Inflate the menu; this adds items to the action bar if it is present.
		getMenuInflater().inflate(R.menu.activity_main, menu);

		return true;
	}

}


本文转载自:http://blog.csdn.net/sfshine/article/details/8451653

共有 人打赏支持
SuShine
粉丝 122
博文 478
码字总数 138638
作品 0
朝阳
后端工程师
《IT蓝豹》listview实现各种版面设计功能

本项目主要listview实现各种版面设计功能,有实现列表的,gridview效果的,有混排效果的等等。 自定义TwoWayView继承RecyclerView,通过TwoWayView去根据布局实现到底选择哪一个效果, 本项目...

抉择很难
2015/11/11
0
0
java.lang.AssertionError Android WebView

先描述下这个问题板块的功能:长文编辑器,图文混排,图片实现懒加载(直接点就是可以,写一篇几十页的长文章,能够自由插图,滑动加载图片)。实现方式,采用webview,结合javascript、htm...

Sn__
07/11
0
0
Android自定义View实现HTML图文环绕效果

Android中并没有提供HTML图文环绕效果的View,最接近的算是TextView中的ImageSpan了,但并未完全实现图文环绕(图文混排)的效果。 1、Android系统TextView的ImageSpan实现图文环绕 代码如下...

带梦想一7飞
2012/11/28
0
0
Android中的File文件存储及读取file中的Bitmap

今年看了下android的文件存储,大致和java实现差不多 android提供了如下两个方法来打开本应用程序的数据文件的IO流: FileInputStream openFileInput(fileName); //输入流 FileOutputStream...

爱吃橙子的小石头
2014/12/07
0
0
Android 动态图文混排的常用方法

DrawableIcon的设置 对于TextView或者EditText动态设置drawableLeft,drawableRight,drawableTop,drawableBottom,drawableStart,drawableEnd的方法总结 Android中提供了许多动态设置的方...

IamOkay
2015/02/07
0
1

没有更多内容

加载失败,请刷新页面

加载更多

下一页

es6

在实际开发中,我们有时需要知道对象的所有属性,原生js给我们提供了一个很好的方法:Object.keys(),该方法返回一个数组 传入对象,返回属性名 var obj = {'a':'123','b':'345'};console.l...

不负好时光
14分钟前
0
0
叮!您收到一份超值Java基础入门资料!

摘要:Java语言有什么特点?如何最大效率的学习?深浅拷贝到底有何区别?阿里巴巴高级开发工程师为大家带来Java系统解读,带你掌握Java技术要领,突破重点难点,入门面向对象编程,以详细示例...

全部原谅
16分钟前
0
0
web.xml容器加载顺序

容器对于web.xml的加载过程是context-param >> listener >> fileter >> servlet

Aeroever
18分钟前
1
0
Docker容器日志查看与清理

1. 问题 docker容器日志导致主机磁盘空间满了。docker logs -f container_name噼里啪啦一大堆,很占用空间,不用的日志可以清理掉了。 2. 解决方法 2.1 找出Docker容器日志 在linux上,容器日...

muzi1994
19分钟前
0
0
J2Cache 和普通缓存框架有何不同,它解决了什么问题?

不少人看到 J2Cache 第一眼时,会认为这就是一个普普通通的缓存框架,和例如 Ehcache、Caffeine 、Spring Cache 之类的项目没什么区别,无非是造了一个新的轮子而已。事实上完全不是一回事!...

红薯
22分钟前
456
14

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部