最近在做文字排版,对于几段文字如果直接用setText,会出现排版混乱现象(末尾如果是标点符号,会和前一个字自动换行)
在网上查了下资料,是android 本身就有这个问题。有说把半角改成全角,但是还是会出现这样的问题。于是只好自己重写了个TextView来排版。网上也有一些人自己实现了,但是好象都挺麻烦的。我针对自己的需要写了个简单的。(不足的是这个TextView还没做自适应,暂时是固定宽度的,自适应需要的可以自己优化);
原理就是计算一行文字的宽度,如果超出了一行宽度,就从下一行开始排。这里有个地方要注意,因为可能文字里包含了多段文本,因此先要分离出每段的"\n"再对一段没有换行符的文字进行每行计算。一开始的时候用最苯的方法,一个字一个字的去计算宽度,虽然实现了效果但是如果文本多了初始化超慢。于是又重新想了一个算法,速度立刻快了很多。
代码如下:
public class JDTextView extends TextView
{
private StringBuffer mText;
/**间隔*/
private int mMarginTop = 0;
private StringBuffer newText = new StringBuffer();
private Paint mPaint;
/**VIEW的高度*/
private int mHeight = 0;
/**行高*/
private static final int LINE_HEIGHT = 40;
/**第一行的位置,因为TEXTVIEW 是从左下角开始算位置的*/
private static final int FIRST_PADDING = 20;
public ClassicalTextView(Context context)
{
super(context);
}
@Override
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
int index = newText.indexOf("\n");
String lineStr;
mMarginTop = FIRST_PADDING;
String tempStr = newText.toString();
while(index != -1)
{
lineStr = tempStr.substring(0, index);
canvas.drawText(lineStr, 0, mMarginTop, mPaint);
tempStr = tempStr.substring(index + 1);
index = tempStr.indexOf("\n");
mMarginTop += LINE_HEIGHT;
}
}
/**
* @Description:计算出一行显示的文字
* @param 设定文件
*/
private String caculateOneLine(String str)
{
//对一段没有\n的文字进行换行
String returnStr = "";
int strWidth = (int) mPaint.measureText(str);
int len = str.length();
int lineNum = strWidth/620; //大概知道分多少行
int oneLine;
int tempWidth = 0;
String lineStr;
int returnInt = 0;
if(lineNum == 0)
{
returnStr = str;
mHeight += LINE_HEIGHT;
return returnStr;
}
else
{
oneLine = len/(lineNum + 1); //一行大概有多少个字
lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);
if(tempWidth < 620) //如果小了 找到大的那个
{
while(tempWidth < 620)
{
oneLine++;
lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);
}
returnInt = oneLine - 1;
returnStr = lineStr.substring(0, lineStr.length() - 2);
}
else
{
while(tempWidth > 620)
{
oneLine--;
lineStr = str.substring(0, oneLine);
tempWidth = (int) mPaint.measureText(lineStr);
}
returnStr = lineStr.substring(0, lineStr.length() - 1);
returnInt = oneLine;
}
mHeight += LINE_HEIGHT;
returnStr += "\n" + caculateOneLine(str.substring(returnInt-1));
}
return returnStr;
}
public void caculateChangeLine()
{
String tempStr[] = mText.toString().split("\n");
int len = tempStr.length;
for(int i=0;i<len;i++)
{
newText.append(caculateOneLine(tempStr[i]));
newText.append("\n");
}
this.setHeight(mHeight);
}
public void setText(String text)
{
mText = new StringBuffer(text);
mPaint = this.getPaint();
caculateChangeLine();
}
}