今天项目没什么进展,公司后台出问题了。看了下刚刚学习Android时的笔记,发现TextView会自动换行,而且排版文字参差不齐。查了下资料,总结原因如下:

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

解决方法一:

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


Java代码
  1. publicstaticStringToDBC(Stringinput){
  2. char[]c=input.toCharArray();
  3. for(inti=0;i<c.length;i++){
  4. if(c[i]==12288){
  5. c[i]=(char)32;
  6. continue;
  7. }if(c[i]>65280&&c[i]<65375)
  8. c[i]=(char)(c[i]-65248);
  9. }
  10. returnnewString(c);
  11. }

解决方法二:

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

Java代码
  1. //替换、过滤特殊字符
  2. publicstaticStringStringFilter(Stringstr)throwsPatternSyntaxException{
  3. str=str.replaceAll("【","[").replaceAll("】","]").replaceAll("!","!");//替换中文标号
  4. StringregEx="[『』]";//清除掉特殊字符
  5. Patternp=Pattern.compile(regEx);
  6. Matcherm=p.matcher(str);
  7. returnm.replaceAll("").trim();
  8. }

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

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

3、一个英文单词不能被显示在两行中( TextView在显示英文时,标点符号是可以放在行尾的,但英文单词也不能分开 )。

4、如果要两行对其的显示效果:有两种方法

方法一:

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

Java代码
  1. if(c==''||c=='/t'||
  2. ((c=='.'||c==','||c==':'||c==';')&&
  3. (j-1<here||!Character.isDigit(chs[j-1-start]))&&
  4. (j+1>=next||!Character.isDigit(chs[j+1-start])))||
  5. ((c=='/'||c=='-')&&
  6. (j+1>=next||!Character.isDigit(chs[j+1-start])))||
  7. (c>=FIRST_CJK&&isIdeographic(c,true)&&
  8. j+1<next&&isIdeographic(chs[j+1-start],false))){
  9. okwidth=w;
  10. ok=j+1;
  11. if(fittop<oktop)
  12. oktop=fittop;
  13. if(fitascent<okascent)
  14. okascent=fitascent;
  15. if(fitdescent>okdescent)
  16. okdescent=fitdescent;
  17. if(fitbottom>okbottom)
  18. okbottom=fitbottom;
  19. }

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

方法二:

自定义View显示文本

网上就有达人采用自定义View来解决这个问题,我做了实验并总结了一下:

自定义View的步骤:

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

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

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

=========================CYTextView.java=============================

Java代码
  1. publicclassCYTextViewextendsTextView{
  2. publicstaticintm_iTextHeight;//文本的高度
  3. publicstaticintm_iTextWidth;//文本的宽度
  4. privatePaintmPaint=null;
  5. privateStringstring="";
  6. privatefloatLineSpace=0;//行间距
  7. publicCYTextView(Contextcontext,AttributeSetset)
  8. {
  9. super(context,set);
  10. TypedArraytypedArray=context.obtainStyledAttributes(set,R.styleable.CYTextView);
  11. intwidth=typedArray.getInt(R.styleable.CYTextView_textwidth,320);
  12. floattextsize=typedArray.getDimension(R.styleable.CYTextView_textSize,24);
  13. inttextcolor=typedArray.getColor(R.styleable.CYTextView_textColor,-1442840576);
  14. floatlinespace=typedArray.getDimension(R.styleable.CYTextView_lineSpacingExtra,15);
  15. inttypeface=typedArray.getColor(R.styleable.CYTextView_typeface,0);
  16. typedArray.recycle();
  17. //设置CYTextView的宽度和行间距www.linuxidc.com
  18. m_iTextWidth=width;
  19. LineSpace=linespace;
  20. //构建paint对象
  21. mPaint=newPaint();
  22. mPaint.setAntiAlias(true);
  23. mPaint.setColor(textcolor);
  24. mPaint.setTextSize(textsize);
  25. switch(typeface){
  26. case0:
  27. mPaint.setTypeface(Typeface.DEFAULT);
  28. break;
  29. case1:
  30. mPaint.setTypeface(Typeface.SANS_SERIF);
  31. break;
  32. case2:
  33. mPaint.setTypeface(Typeface.SERIF);
  34. break;
  35. case3:
  36. mPaint.setTypeface(Typeface.MONOSPACE);
  37. break;
  38. default:
  39. mPaint.setTypeface(Typeface.DEFAULT);
  40. break;
  41. }
  42. }
  43. @Override
  44. protectedvoidonDraw(Canvascanvas)
  45. {
  46. super.onDraw(canvas);
  47. charch;
  48. intw=0;
  49. intistart=0;
  50. intm_iFontHeight;
  51. intm_iRealLine=0;
  52. intx=2;
  53. inty=30;
  54. Vectorm_String=newVector();
  55. FontMetricsfm=mPaint.getFontMetrics();
  56. m_iFontHeight=(int)Math.ceil(fm.descent-fm.top)+(int)LineSpace;//计算字体高度(字体高度+行间距)
  57. for(inti=0;i<string.length();i++)
  58. {
  59. ch=string.charAt(i);
  60. float[]widths=newfloat[1];
  61. Stringsrt=String.valueOf(ch);
  62. mPaint.getTextWidths(srt,widths);
  63. if(ch=='/n'){
  64. m_iRealLine++;
  65. m_String.addElement(string.substring(istart,i));
  66. istart=i+1;
  67. w=0;
  68. }else{
  69. w+=(int)(Math.ceil(widths[0]));
  70. if(w>m_iTextWidth){
  71. m_iRealLine++;
  72. m_String.addElement(string.substring(istart,i));
  73. istart=i;
  74. i--;
  75. w=0;
  76. }else{
  77. if(i==(string.length()-1)){
  78. m_iRealLine++;
  79. m_String.addElement(string.substring(istart,string.length()));
  80. }
  81. }
  82. }
  83. }
  84. m_iTextHeight=m_iRealLine*m_iFontHeight+2;
  85. canvas.setViewport(m_iTextWidth,m_iTextWidth);
  86. for(inti=0,j=0;i<m_iRealLine;i++,j++)
  87. {
  88. canvas.drawText((String)(m_String.elementAt(i)),x,y+m_iFontHeight*j,mPaint);
  89. }
  90. }
  91. protectedvoidonMeasure(intwidthMeasureSpec,intheightMeasureSpec)
  92. {
  93. intmeasuredHeight=measureHeight(heightMeasureSpec);
  94. intmeasuredWidth=measureWidth(widthMeasureSpec);
  95. this.setMeasuredDimension(measuredWidth,measuredHeight);
  96. this.setLayoutParams(newLinearLayout.LayoutParams(measuredWidth,measuredHeight));
  97. super.onMeasure(widthMeasureSpec,heightMeasureSpec);
  98. }
  99. privateintmeasureHeight(intmeasureSpec)
  100. {
  101. intspecMode=MeasureSpec.getMode(measureSpec);
  102. intspecSize=MeasureSpec.getSize(measureSpec);
  103. //Defaultsizeifnolimitsarespecified.
  104. initHeight();
  105. intresult=m_iTextHeight;
  106. if(specMode==MeasureSpec.AT_MOST){
  107. //Calculatetheidealsizeofyour
  108. //controlwithinthismaximumsize.
  109. //Ifyourcontrolfillstheavailable
  110. //spacereturntheouterbound.
  111. result=specSize;
  112. }elseif(specMode==MeasureSpec.EXACTLY){
  113. //Ifyourcontrolcanfitwithintheseboundsreturnthatvalue.
  114. result=specSize;
  115. }
  116. returnresult;
  117. }
  118. privatevoidinitHeight()
  119. {
  120. //设置CYTextView的初始高度为0
  121. m_iTextHeight=0;
  122. //大概计算CYTextView所需高度
  123. FontMetricsfm=mPaint.getFontMetrics();
  124. intm_iFontHeight=(int)Math.ceil(fm.descent-fm.top)+(int)LineSpace;
  125. intline=0;
  126. intistart=0;
  127. intw=0;
  128. for(inti=0;i<string.length();i++)
  129. {
  130. charch=string.charAt(i);
  131. float[]widths=newfloat[1];
  132. Stringsrt=String.valueOf(ch);
  133. mPaint.getTextWidths(srt,widths);
  134. if(ch=='/n'){
  135. line++;
  136. istart=i+1;
  137. w=0;
  138. }else{
  139. w+=(int)(Math.ceil(widths[0]));
  140. if(w>m_iTextWidth){
  141. line++;
  142. istart=i;
  143. i--;
  144. w=0;
  145. }else{
  146. if(i==(string.length()-1)){
  147. line++;
  148. }
  149. }
  150. }
  151. }
  152. m_iTextHeight=(line)*m_iFontHeight+2;
  153. }
  154. privateintmeasureWidth(intmeasureSpec)
  155. {
  156. intspecMode=MeasureSpec.getMode(measureSpec);
  157. intspecSize=MeasureSpec.getSize(measureSpec);
  158. //Defaultsizeifnolimitsarespecified.
  159. intresult=500;
  160. if(specMode==MeasureSpec.AT_MOST){
  161. //Calculatetheidealsizeofyourcontrol
  162. //withinthismaximumsize.
  163. //Ifyourcontrolfillstheavailablespace
  164. //returntheouterbound.
  165. result=specSize;
  166. }elseif(specMode==MeasureSpec.EXACTLY){
  167. //Ifyourcontrolcanfitwithintheseboundsreturnthatvalue.
  168. result=specSize;
  169. }
  170. returnresult;
  171. }
  172. publicvoidSetText(Stringtext)(//注:此函数目前只有在UI线程中调用才可以把文本画出来,在其它线程中<p>//无法画文本,找了好久找不到原因,求高手解答)
  173. {
  174. string=text;
  175. //requestLayout();
  176. //invalidate();
  177. }
  178. }</p>

=======================attrs.xml===============================

该文件是自定义的属性,放在工程的res/values下

Java代码
  1. <resources>
  2. <attrname="textwidth"format="integer"/>
  3. <attrname="typeface">
  4. <enumname="normal"value="0"/>
  5. <enumname="sans"value="1"/>
  6. <enumname="serif"value="2"/>
  7. <enumname="monospace"value="3"/>
  8. </attr>
  9. <declare-styleablename="CYTextView">
  10. <attrname="textwidth"/>
  11. <attrname="textSize"format="dimension"/>
  12. <attrname="textColor"format="reference|color"/>
  13. <attrname="lineSpacingExtra"format="dimension"/>
  14. <attrname="typeface"/>
  15. </declare-styleable>
  16. </resources>

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

Java代码
  1. <?xmlversion="1.0"encoding="utf-8"?>
  2. <ScrollView
  3. xmlns:Android="http://schemas.android.com/apk/res/android"
  4. Android:layout_width="320px"
  5. Android:layout_height="320px"
  6. Android:background="#ffffffff"
  7. >
  8. <LinearLayout
  9. xmlns:Android="http://schemas.android.com/apk/res/android"
  10. Android:orientation="vertical"
  11. Android:layout_width="fill_parent"
  12. Android:layout_height="fill_parent">
  13. <com.cy.CYTextView.CYTextView
  14. xmlns:cy="http://schemas.Android.com/apk/res/com.cy.CYTextView"
  15. Android:id="@+id/mv"
  16. Android:layout_height="wrap_content"
  17. Android:layout_width="wrap_content"
  18. cy:textwidth="320"
  19. cy:textSize="24sp"
  20. cy:textColor="#aa000000"
  21. cy:lineSpacingExtra="15sp"
  22. cy:typeface="serif">
  23. </com.cy.CYTextView.CYTextView>
  24. </LinearLayout>
  25. </ScrollView>

蓝色代码即为自定义View,其中以cy命名空间开头的属性是自定义属性;

=======================Main.java=============================

Java代码
  1. publicclassMainextendsActivity{
  2. CYTextViewmCYTextView;
  3. Stringtext="Android提供了精巧和有力的组件化模型构建用户的UI部分。主要是基于布局类:View和ViewGroup。在此基础上,android平台提供了大量的预制的View和xxxViewGroup子类,即布局(layout)和窗口小部件(widget)。可以用它们构建自己的UI。";
  4. @Override
  5. publicvoidonCreate(BundlesavedInstanceState){
  6. super.onCreate(savedInstanceState);
  7. this.setContentView(R.layout.main);
  8. mCYTextView=(CYTextView)findViewById(R.id.mv);
  9. mCYTextView.SetText(text);
  10. }
  11. }

更多相关文章

  1. 【Bugly干货分享】手把手教你逆向分析 Android(安卓)程序
  2. Flutter调用Android和iOS原生代码的方法示例
  3. Android(安卓)sdk 简单的客户端源代码
  4. 破解某国外收费的RTMP Client并成功在Android和Java上调用
  5. Android(安卓)Studio 和 Unity 之间实现代码交互aar模式
  6. Android(安卓)弹无虚发之第二弹:Android(安卓)ActionBar 的其它用
  7. android 代码设置、打开wifi热点及热点的连接
  8. Android项目源码质量检测
  9. Android逆向之旅---静态分析技术来破解Apk

随机推荐

  1. Android(安卓)UI 基本布局 weight 在 Lin
  2. node.js+Android(安卓)http请求响应
  3. Android(安卓)的 CRUD
  4. android为listView添加表头
  5. Android(安卓)service传递的问题
  6. Android(安卓)自动化测试―robotium(四)Che
  7. 用gdb调试 android webkit
  8. [置顶] Cocos2d android(一个小时学会Fly
  9. Eclipse 插件安装方法和插件加载失败解决
  10. android 服务不被kill方法收集