Android TextView的自动换行会导致文本排版参差不齐,大概原因如下:
一:全角字符和半角字符混乱使用
常见于汉字字符和数字、英文字符混合使用。
解决办法:
将text中的字符全角化,即将所有的数字、字母、标点符号全部转为全角字符,
使他们同汉字一样占用两个字节,这样就可以避免由于占位混乱导致的排版混乱问题,转换代码如下:
public static String ToDBC(String input) { char[] c = input.toCharArray(); for (int i = 0; i< c.length; i++) { if (c[i] == 12288) { c[i] = (char) 32; continue; }if (c[i]> 65280&& c[i]< 65375) c[i] = (char) (c[i] - 65248); } return new String(c); }
二:全角字符和半角字符混乱使用
TextView在显示中文的时候标点符号不能显示在一行的行首和行尾,如果一个标点符号刚好在一行的行尾,
该标点符号就会连同前一个字符自动换到下一行显示。
解决办法:
在该标点符号后面添加一个空格。
三:一个英文单词不能被显示在两行中
TextView在显示英文时,标点符号是可以放在行尾的,但英文单词不能分开。
两行对齐:实现两行对齐的显示效果
解决办法一:
修改Android源代码;将frameworks/base/core/java/android/text下的StaticLayout.java文件中的如下代码 去掉:
去掉后标点符号可以显示在行首和行尾,英文单词也可以被分开在两行中显示。if (c == ' ' || c == '/t' || ((c == '.' || c == ',' || c == ':' || c == ';') && (j - 1 < here || !Character.isDigit(chs[j - 1 - start])) && (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || ((c == '/' || c == '-') && (j + 1 >= next || !Character.isDigit(chs[j + 1 - start]))) || (c >= FIRST_CJK && isIdeographic(c, true) && j + 1 < next && isIdeographic(chs[j + 1 - start], false))) { okwidth = w; ok = j + 1; if (fittop < oktop) oktop = fittop; if (fitascent < okascent) okascent = fitascent; if (fitdescent > okdescent) okdescent = fitdescent; if (fitbottom > okbottom) okbottom = fitbottom; }
解决办法二:
package rong.android.test; import org.json.JSONArray; import org.json.JSONException; import android.content.Context; import android.graphics.Canvas; import android.graphics.Color; import android.graphics.Paint; import android.util.AttributeSet; import android.view.View; import android.widget.TextView; public class XRTextView extends TextView{ private final String namespace = "rong.android.TextView"; private String text; private float textSize; private float paddingLeft; private float paddingRight; private float marginLeft; private float marginRight; private int textColor; private JSONArray colorIndex; private Paint paint1 = new Paint(); private Paint paintColor = new Paint(); private float textShowWidth; private float Spacing = 0; private float LineSpacing = 1.3f;//行与行的间距 public XRTextView(Context context, AttributeSet attrs) { super(context, attrs); text = attrs.getAttributeValue( "http://schemas.android.com/apk/res/android", "text"); textSize = attrs.getAttributeIntValue(namespace, "textSize", 25);//字体大小 textColor = attrs.getAttributeIntValue(namespace, "textColor",Color.BLUE);//字体颜色 paddingLeft = attrs.getAttributeIntValue(namespace, "paddingLeft", 0); paddingRight = attrs.getAttributeIntValue(namespace, "paddingRight", 0); marginLeft = attrs.getAttributeIntValue(namespace, "marginLeft", 0); marginRight = attrs.getAttributeIntValue(namespace, "marginRight", 0); paint1.setTextSize(textSize); paint1.setColor(textColor); paint1.setAntiAlias(true); paintColor.setAntiAlias(true); paintColor.setTextSize(textSize); paintColor.setColor(Color.BLUE); } public XRTextView(Context context, float textSize, int textColor, float paddingLeft, float paddingRight, float marginLeft, float marginRight){ super(context); this.textSize = textSize; this.textColor = textColor; this.paddingLeft = paddingLeft; this.paddingRight = paddingRight; this.marginLeft = marginLeft; this.marginRight = marginRight; paint1.setTextSize(textSize); paint1.setColor(textColor); paint1.setAntiAlias(true); paintColor.setAntiAlias(true); paintColor.setTextSize(textSize); paintColor.setColor(Color.BLUE); } public JSONArray getColorIndex() { return colorIndex; } public void setColorIndex(JSONArray colorIndex) { this.colorIndex = colorIndex; } /** * 传入一个索引,判断当前字是否被高亮 * @param index * @return * @throws JSONException */ public boolean isColor(int index) throws JSONException{ if(colorIndex == null){ return false; } for(int i = 0 ; i < colorIndex.length() ; i ++){ JSONArray array = colorIndex.getJSONArray(i); int start = array.getInt(0); int end = array.getInt(1)-1; if(index >= start && index <= end){ return true; } } return false; } @Override protected void onDraw(Canvas canvas) { // super.onDraw(canvas); View view=(View)this.getParent(); textShowWidth=view.getMeasuredWidth() - paddingLeft - paddingRight - marginLeft - marginRight; int lineCount = 0; text = this.getText().toString();//.replaceAll("\n", "\r\n"); if(text==null)return; char[] textCharArray = text.toCharArray(); // 已绘的宽度 float drawedWidth = 0; float charWidth; for (int i = 0; i < textCharArray.length; i++) { charWidth = paint1.measureText(textCharArray, i, 1); if(textCharArray[i]=='\n'){ lineCount++; drawedWidth = 0; continue; } if (textShowWidth - drawedWidth < charWidth) { lineCount++; drawedWidth = 0; } boolean color = false; try { color = isColor(i); } catch (JSONException e1) { e1.printStackTrace(); } if(color){ canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth, (lineCount + 1) * textSize * LineSpacing, paintColor); }else{ canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth, (lineCount + 1) * textSize * LineSpacing, paint1); } if(textCharArray[i] > 127 && textCharArray[i] != '、' && textCharArray[i] != ',' && textCharArray[i] != '。' && textCharArray[i] != ':' && textCharArray[i] != '!'){ drawedWidth += charWidth + Spacing; }else{ drawedWidth += charWidth; } } setHeight((int) ((lineCount + 1) * (int) textSize * LineSpacing + 10)); } public float getSpacing() { return Spacing; } public void setSpacing(float spacing) { Spacing = spacing; } public float getMYLineSpacing() { return LineSpacing; } public void setMYLineSpacing(float lineSpacing) { LineSpacing = lineSpacing; } public float getMYTextSize() { return textSize; } public void setMYTextSize(float textSize) { this.textSize = textSize; paint1.setTextSize(textSize); paintColor.setTextSize(textSize); } }