Android TextView自动换行文字排版参差不齐的原因及处理

TextView或者EditView中的长的英文单词会自动换行,从而导致排版文字参差不齐。大致的原因及相应的解决办法如下:

一:原因之一:半角字符与全角字符混乱所致:这种情况一般就是汉字与数字、英文字母混用

解决方法1:

将textview中的字符全角化。即将所有的数字、字母及标点全部转为全角字符,使它们与汉字同占两个字节,这样就可以避免由于占位导致的排版混乱问题了。 半角转为全角的代码如下,只需调用即可。

<span style="font-family:Microsoft YaHei;font-size:12px;">/**
     * 全角转半角的函数(DBC case) 全角空格为12288,半角空格为32
     * 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
     * 
     * @param input 任意字符串
     * @return
     */
    public static String SBCToDBC(String input) {
        if (input == null || "".equals(input)) {
            return "";
        }
        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);
    }

    /**
     * 半角转转全角的函数(SBC case) 全角空格为12288,半角空格为32
     * 其他字符半角(33-126)与全角(65281-65374)的对应关系是:均相差65248
     * 
     * @param input
     * @return
     */
    public static String DBCToSBC(String input) {
        char[] c = input.toCharArray();
        for (int i = 0; i < c.length; i++) {
            if (c[i] == 32) {
                c[i] = (char) 12288;
                continue;
            }
            if (c[i] < 127)
                c[i] = (char) (c[i] + 65248);
        }
        return new String(c);
    }</span>

 解决方法2:

去除特殊字符或将所有中文标号替换为英文标号。利用正则表达式将所有特殊字符过滤,或利用replaceAll()将中文标号替换为英文标号。则转化之后,则可解决排版混乱问题。

<span style="font-family:Microsoft YaHei;font-size:12px;">// 替换、过滤特殊字符
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();
}</span>

二:原因之二:TextView在显示中文的时候标点符号不能显示在一行的行首和行尾,如果一个标点符号刚好在一行的行尾,该标点符号就会连同前一个字符跳到下一行显示。

解决方法1:在标点符号后加一个空格。

      三:原因之三:一个英文单词不能被显示在两行中( TextView在显示英文时,标点符号是可以放在行尾的,但英文单词也不能分开 )。如果要两行对其的显示效果:有两种方法

解决方法1:

修改Android源代码;将frameworks/base/core/java/android/text下的StaticLayout.java文件中的如下代码:

<span style="font-family:Microsoft YaHei;font-size:12px;">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;
                        }</span>

去掉就可以了。去掉后标点符号可以显示在行首和行尾,英文单词也可以被分开在两行中显示。


解决方法2:

自定义View控件,自己控制View的显示来解决这个问题:

自定义View的步骤: 

(1)继承View类或其子类,例子继承了TextView类;

(2)写构造函数,通过XML获取属性(这一步中可以自定义属性,见例程);

(3)重写父类的某些函数,一般都是以on开头的函数,例子中重写了onDraw()和onMeasure()函数;

以下是自定view类文件:

<span style="font-family:Microsoft YaHei;font-size:12px;">=========================MyTextView.java=============================

public class MyTextView 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 MyTextView(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;
 }
 @Override
 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);
 }
}</span>
以下是布局XML文档:

=======================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.MyTextView
        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类文件:

<span style="font-family:Microsoft YaHei;">=======================MainActivity.java=============================

public class MainActivity extends Activity {
     MyTextView view;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        
        view = (MyTextView) 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();
 }
}</span>




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值