android中textview显示自汗,字母,数字乱行行问题解决

来源:互联网 发布:java后端开发做什么的 编辑:程序博客网 时间:2024/05/01 11:19
原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 、作者信息和本声明。否则将追究法律责任。http://2960629.blog.51cto.com/2950629/636828

 

默认EditText和TextView自动换行。如果在string中出现了中文字符,排版出现意外,如图所示:

 

这是因为软盘默认的是半角输入,而字母与数字的占位与汉字不同,所以在默认的情况下会出现如上的排版情况。

但是如果将默认的半角变成全角之后就可以基本解决排版问题:

 

 

虽然全角看上去不好看,但是基本不会出现参差不齐。暂时没有找到其他的解决方法,如果不喜欢全角的效果,看来只能用canvas画上去了。。。

代码:

  mTextWrite = (EditText) findViewById(R.id.note_editor_write);// 得到写文本框
  //将输入的字母全部变成全角
  mTextWrite.setOnKeyListener(new EditText.OnKeyListener() {

   @Override
   public boolean onKey(View v, int keyCode, KeyEvent event) {
    // TODO Auto-generated method stub
    String temp = mTextWrite.getText().toString();
    mTextWrite.setText("");
    mTextWrite.append(ToSBC(temp));
    return false;
   }

  });

 // 半角转化为全角的方法
 public String ToSBC(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]>32)
    c[i] = (char) (c[i] + 65248);

  }
  return new String(c);
 }

 // 全角转化为半角的方法

 public String ToDBC(String input) {
  char[] c = input.toCharArray();
  for (int i = 0; i < c.length; i++) {
   if (isChinese(c[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);
 }

 

ps:利用编码的方式判断字符是否为汉字的方法:

 private boolean isChinese(char c) {
  Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
  if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS
    || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
    || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A
    || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION
    || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION
    || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
   return true;
  }
  return false;
 }

 

pps:出现排版错误的另一个情况:

        android textview自动换行时为了保持单词的完整性,单词不会因为换行而断开。

解决方法:计算字符串长度,然后手动设定每一行显示多少个字母并加上‘\n‘

本文出自 “Alex_Michel” 博客,请务必保留此出处http://2960629.blog.51cto.com/2950629/636828



 转自:

  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("!","!");//替换中文标号
  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 = "";
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("", "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);
}
}

  =======================main.xml===============================

  <RelativeLayout xmlns:android=""
  xmlns: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();
}
}


0 0