zoukankan      html  css  js  c++  java
  • Android TextView自动换行文字排字参差不齐的原因及处理

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

      转自:

      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(" ", " ");
     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]==' '){
      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 += (" ");
      sb.append(line);
      }
      reader.close();
      in.close();
     } catch (IOException e) {
      e.printStackTrace();
     }
     return sb.toString();
    }
    }

  • 相关阅读:
    《objective-c基础教程》学习笔记(三)—— 从结构体到面向对象
    《objective-c基础教程》学习笔记(二)—— for循环的基本应用
    《objective-c基础教程》学习笔记 (一)—— 开发环境配置和简单类型输出
    asp.net mvc 3.0 知识点整理 ----- (4).asp.net mvc 3 和asp.net mvc 4 对比
    git简单使用(上篇)
    git简单使用(下篇)
    Spring核心概念之Ioc
    "注解"的用法
    struts2进阶篇(3)
    struts2进阶篇(2)
  • 原文地址:https://www.cnblogs.com/zyppac/p/3937806.html
Copyright © 2011-2022 走看看