Android 自绘TextView解决提前换行问题,支持图文混排

 

 

先看下效果图:

上面是MTextView,下面是默认的TextView。

 

一、原因

用最简单的全英文句子为例,如果有一个很长的单词,这一行剩余的空间显示不下了,那么规则就是不打断单词,而是把整个单词丢到下一行开始显示。这样本来没有错。一是咱们中国人都是方块字,怎么都放得下,不存在英文的这个问题。所以不习惯那个排版。二是如果TextView里面有图片,如图,不知道判断单词的代码是怎么弄得,总之它觉得最后一个啦字和后面的一串表情应该是一个整体,不能分开,就一起丢到第二行了,也就造成了这种难看的排版。要验证这个说法也很简单,自己去QQ里试一试,在每个表情之间都加一个空格,就会发现排版一下子正常了。

二、解决方法

    最简单的就是表情之间加空格,如果不想这么做,就只有自己来画啦。

    先给初学的朋友解释一下View绘制的流程,首先是onMeasure(int widthMeasureSpec, int heightMeasureSpec),onMeasure执行的时候,就是父View在问你,小朋友,你要占多大的地儿呀?当然,问你的时候,会给你个限制条件,就是那两参数,以widthMeasureSpec为例,这参数不能直接用,得先拆开,用int widthMode = MeasureSpec.getMode(widthMeasureSpec) 和 int widthSize = MeasureSpec.getSize(widthMeasureSpec);widthMode就三种情况:

MeasureSpec.EXACTLY:你就widthSize那么宽就行了。

MeasureSpec.AT_MOST:你最多只能widthSize那么宽。

MeasureSpec.UNSPECIFIED:未指定,你爱多宽多宽。

当然,其实这只父View给你的建议,遵不遵守你自己看着办,但是自己乱来导致显示不全就不是父View的错了。

最终你听取了建议,思量了一番,觉得自己应该有width那么宽,height那么高,最后就得用setMeasuredDimension(width, height)这个函数真正确定自己的高宽。然后onMeasure()的工作就完了。

然后就是onDraw(Canvas canvas),这个就简单了,canvas就是父View给的一块画布,爱在上面画啥都行,比如写个字drawText(String text,float x, float y, Paint paint),

text是要写的字,paint是写字的笔,值得注意的是x,y坐标是相对于你自己这一小块画布的左上角的。最左上就是0,0右下是width,height

 

上代码

</pre><pre>

/**
 * @author huangwei
 * @version SocialClient 1.2.0
 * @功能 图文混排TextView,请使用{@link #setMText(CharSequence)}
 * @2014年5月27日
 * @下午5:29:27
 */
public class MTextView extends TextView
{
	/**
	 * 缓存测量过的数据
	 */
	private static HashMap<String, SoftReference<MeasuredData>> measuredData = new HashMap<String, SoftReference<MeasuredData>>();
	private static int hashIndex = 0;
	/**
	 * 存储当前文本内容,每个item为一行
	 */
	ArrayList<LINE> contentList = new ArrayList<LINE>();
	private Context context;
	/**
	 * 用于测量字符宽度
	 */
	private TextPaint paint = new TextPaint();
	
//	private float lineSpacingMult = 0.5f;
	private int textColor = Color.BLACK;
	//行距
	private float lineSpacing;
	private int lineSpacingDP = 5;
	/**
	 * 最大宽度
	 */
	private int maxWidth;
	/**
	 * 只有一行时的宽度
	 */
	private int oneLineWidth = -1;
	/**
	 * 已绘的行中最宽的一行的宽度
	 */
	private float lineWidthMax = -1;
	/**
	 * 存储当前文本内容,每个item为一个字符或者一个SpanObject
	 */
	private ArrayList<Object> obList = new ArrayList<Object>();
	/**
	 * 是否使用默认{@link #onMeasure(int, int)}和{@link #onDraw(Canvas)}
	 */
	private boolean useDefault = false;
	private CharSequence text = "";

	private int minHeight;
	/**
	 * 用以获取屏幕高宽
	 */
	private DisplayMetrics displayMetrics;
	/**
	 * {@link android.text.style.BackgroundColorSpan}用
	 */
	private Paint textBgColorPaint = new Paint()
  • 7
    点赞
  • 30
    收藏
    觉得还不错? 一键收藏
  • 21
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 21
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值