转自:http://zhxhinfu.blog.163.com/blog/static/1875711882012725118194/
?
TextView会自动换行,而且排版文字参差不齐。查了下资料,总结原因如下:
1、半角字符与全角字符混乱所致:这种情况一般就是汉字与数字、英文字母混用
解决方法一:
将textview中的字符全角化。即将所有的数字、字母及标点全部转为全角字符,使它们与汉字同占两个字节,这样就可以避免由于占位导致的排版混乱问题了。 半角转为全角的代码如下,只需调用即可。
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);
}
?解决方法二:
去除特殊字符或将所有中文标号替换为英文标号。利用正则表达式将所有特殊字符过滤,或利用replaceAll()将中文标号替换为英文标号。则转化之后,则可解决排版混乱问题。
?// 替换、过滤特殊字符
public static String StringFilter(String str) throws PatternSyntaxException{
??? str=str.replaceAll("【","[").replaceAll("】","]").replaceAll("!","!");//替换中文标号
??? String regEx="[『』]"; // 清除掉特殊字符
??? Pattern p = Pattern.compile(regEx);
??? Matcher m = p.matcher(str);
?return m.replaceAll("").trim();
}
?
2、TextView在显示中文的时候标点符号不能显示在一行的行首和行尾,如果一个标点符号刚好在一行的行尾,该标点符号就会连同前一个字符跳到下一行显示。
解决方法:在标点符号后加一个空格。
?
3、一个英文单词不能被显示在两行中( TextView在显示英文时,标点符号是可以放在行尾的,但英文单词也不能分开 )。
?
4、如果要两行对其的显示效果:有两种方法
方法一:
修改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;
??????????????????????? }
去掉就可以了。去掉后标点符号可以显示在行首和行尾,英文单词也可以被分开在两行中显示。
?
方法二:
自定义View显示文本
网上就有达人采用自定义View来解决这个问题,我做了实验并总结了一下:
自定义View的步骤:?
1)继承View类或其子类,例子继承了TextView类;
2)写构造函数,通过XML获取属性(这一步中可以自定义属性,见例程);
3)重写父类的某些函数,一般都是以on开头的函数,例子中重写了onDraw()和onMeasure()函数;
?
以下是代码
=========================MyTextView2.java=============================
public class MyTextView2 extends TextView{
?private final String namespace = "http://www.angellecho.com/";
?private String text;
?private float textSize;
?private float paddingLeft;
?private float paddingRight;
?private float marginLeft;
?private float marginRight;
?private int textColor;
?private Paint paint1 = new Paint();
?private float textShowWidth;
?public MyTextView2(Context context, AttributeSet attrs) {
??super(context, attrs);
??text = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "text");
??textSize = attrs.getAttributeIntValue(namespace, "textSize", 15);
??textColor = attrs.getAttributeIntValue(namespace, "textColor",Color.WHITE);
??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);
??textShowWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth() - paddingLeft - paddingRight - marginLeft - marginRight;
?}
[email protected]
?protected void onDraw(Canvas canvas) {
??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;
???}
???canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth,
?????(lineCount + 1) * textSize, paint1);
???drawedWidth += charWidth;
??}
??setHeight((lineCount + 1) * (int) textSize + 5);
?}
}
=======================main.xml===============================
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
??? xmlns:tools="http://schemas.android.com/tools"
??? android:layout_width="match_parent"
??? android:layout_height="match_parent"
??? android:background="@android:color/black" >
??? <com.wigit.MyTextView2
??????? android:id="@+id/view"
??????? android:layout_width="fill_parent"
??????? android:layout_height="fill_parent"
??????? android:textColor="@android:color/white"
??????? android:textSize="20dip" />
</RelativeLayout>
?
=======================MainActivity.java=============================
public class MainActivity extends Activity {
???? MyTextView2 view;
??? @Override
??? public void onCreate(Bundle savedInstanceState) {
??????? super.onCreate(savedInstanceState);
??????? setContentView(R.layout.activity_main);
???????
??????? view = (MyTextView2) findViewById(R.id.view);
??????? view.setText(getAssetsString(this,"1.txt"));
??????? view.setMovementMethod(ScrollingMovementMethod.getInstance());
??? }
?public String getAssetsString(Context context,String fileName){
??StringBuffer sb = new StringBuffer();
??//根据语言选择加载
??try {
???AssetManager am = context.getAssets();
???InputStream in = am.open(fileName);
???BufferedReader reader = new BufferedReader(new InputStreamReader(in));
???String line;
???while((line = reader.readLine())!=null){
????line += ("\n");
????sb.append(line);
???}
???reader.close();
???in.close();
??} catch (IOException e) {
???e.printStackTrace();
??}
??return sb.toString();
?}
}