Android TextView 自动换行问题

Android的TextView在显示文字的时候有个问题就是一行还没显示满就跳到下一行,原因是:

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

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

如果只是想让标点符号可以显示在行尾,有一个简单的方法就是在标点符号后加一个空格,则该标点符号就可以显示在行尾了;

如果想要两端对齐的显示效果,有两种方法:

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

[java]  view plain copy
  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.   
  12. if (fittop < oktop)  
  13. oktop = fittop;  
  14. if (fitascent < okascent)  
  15. okascent = fitascent;  
  16. if (fitdescent > okdescent)  
  17. okdescent = fitdescent;  
  18. if (fitbottom > okbottom)  
  19. okbottom = fitbottom;  
  20. }   


 

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

2)自定义View显示文本

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

自定义View的步骤:

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

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

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

=========================StartCustomTextView.java=============================

[java]  view plain copy
  1. public class StartCustomTextView extends TextView {  
  2.     public  static  int m_iTextHeight; //文本的高度  
  3.     public  static  int m_iTextWidth;//文本的宽度  
  4.       
  5.     private Paint mPaint = null;  
  6.     private String string="";  
  7.     private float LineSpace = 0;//行间距  
  8.     private int left_Margin;  
  9.     private int right_Margin;  
  10.     private int bottom_Margin;  
  11.           
  12.     public StartCustomTextView(Context context, AttributeSet set)   
  13.     {         
  14.         super(context,set);    
  15.         DisplayMetrics displayMetrics = getResources().getDisplayMetrics();  
  16.         TypedArray typedArray = context.obtainStyledAttributes(set, R.styleable.CYTextView);  
  17.         int width = displayMetrics.widthPixels;  
  18.         left_Margin = 29;  
  19.         right_Margin = 29;  
  20.         bottom_Margin = 29;  
  21.         width = width - left_Margin -right_Margin;  
  22.         float textsize = typedArray.getDimension(R.styleable.CYTextView_textSize, 34);  
  23.         int textcolor = typedArray.getColor(R.styleable.CYTextView_textColor, getResources().getColor(R.color.white));  
  24.         float linespace = typedArray.getDimension(R.styleable.CYTextView_lineSpacingExtra, 15);  
  25.         int typeface = typedArray.getColor(R.styleable.CYTextView_typeface, 0);  
  26.           
  27.         typedArray.recycle();  
  28.           
  29.         //设置 CY TextView的宽度和行间距www.linuxidc.com  
  30.         m_iTextWidth=width;  
  31.         LineSpace=linespace;  
  32.           
  33.         // 构建paint对象        
  34.         mPaint = new Paint();  
  35.         mPaint.setAntiAlias(true);  
  36.         mPaint.setColor(textcolor);  
  37.         mPaint.setTextSize(textsize);  
  38.         switch(typeface){  
  39.         case 0:  
  40.             mPaint.setTypeface(Typeface.DEFAULT);  
  41.             break;  
  42.         case 1:  
  43.             mPaint.setTypeface(Typeface.SANS_SERIF);  
  44.             break;  
  45.         case 2:  
  46.             mPaint.setTypeface(Typeface.SERIF);  
  47.             break;  
  48.         case 3:  
  49.             mPaint.setTypeface(Typeface.MONOSPACE);  
  50.             break;  
  51.         default:  
  52.             mPaint.setTypeface(Typeface.DEFAULT);      
  53.             break;  
  54.         }  
  55.           
  56.     }  
  57.     
  58.     @Override  
  59.     protected void onDraw(Canvas canvas)   
  60.     {    
  61.        super.onDraw(canvas);         
  62.           
  63.         char ch;  
  64.         int w = 0;  
  65.         int istart = 0;  
  66.         int m_iFontHeight;  
  67.         int m_iRealLine=0;  
  68.         int x=2;  
  69.         int y=30;  
  70.           
  71.         Vector   m_String=new Vector();  
  72.           
  73.         FontMetrics fm = mPaint.getFontMetrics();          
  74.         m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int)LineSpace;//计算字体高度(字体高度+行间距)  
  75.   
  76.         for (int i = 0; i < string.length(); i++)  
  77.         {  
  78.             ch = string.charAt(i);  
  79.             float[] widths = new float[1];  
  80.             String srt = String.valueOf(ch);  
  81.             mPaint.getTextWidths(srt, widths);  
  82.   
  83.             if (ch == '\n'){  
  84.                 m_iRealLine++;  
  85.                 m_String.addElement(string.substring(istart, i));  
  86.                 istart = i + 1;  
  87.                 w = 0;  
  88.             }else{  
  89.                 w += (int) (Math.ceil(widths[0]));  
  90.                 if (w > m_iTextWidth){  
  91.                     m_iRealLine++;  
  92.                     m_String.addElement(string.substring(istart, i));  
  93.                     istart = i;  
  94.                     i--;  
  95.                     w = 0;  
  96.                 }else{  
  97.                     if (i == (string.length() - 1)){  
  98.                         m_iRealLine++;  
  99.                         m_String.addElement(string.substring(istart, string.length()));  
  100.                     }  
  101.                 }  
  102.             }  
  103.         }  
  104.         m_iTextHeight=m_iRealLine*m_iFontHeight+2;  
  105.         canvas.setViewport(m_iTextWidth, m_iTextWidth);  
  106.         for (int i = 0, j = 0; i < m_iRealLine; i++, j++)  
  107.         {  
  108.             canvas.drawText((String)(m_String.elementAt(i)), x,  y+m_iFontHeight * j, mPaint);  
  109.         }  
  110.     }    
  111.      
  112.       
  113.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec)   
  114.     {            
  115.         int measuredHeight = measureHeight(heightMeasureSpec);            
  116.         int measuredWidth = measureWidth(widthMeasureSpec);             
  117.         this.setMeasuredDimension(measuredWidth, measuredHeight);  
  118.         LayoutParams layout = new LinearLayout.LayoutParams(measuredWidth,measuredHeight);  
  119.         layout.leftMargin= left_Margin;  
  120.         layout.rightMargin= right_Margin;  
  121.         layout.bottomMargin= bottom_Margin;  
  122.         this.setLayoutParams(layout);  
  123.         super.onMeasure(widthMeasureSpec, heightMeasureSpec);  
  124.     }    
  125.                    
  126.     private int measureHeight(int measureSpec)   
  127.     {    
  128.         int specMode = MeasureSpec.getMode(measureSpec);            
  129.         int specSize = MeasureSpec.getSize(measureSpec);                     
  130.         // Default size if no limits are specified.    
  131.         initHeight();  
  132.         int result = m_iTextHeight;            
  133.         if (specMode == MeasureSpec.AT_MOST){           
  134.             // Calculate the ideal size of your            
  135.             // control within this maximum size.            
  136.             // If your control fills the available             
  137.             // space return the outer bound.            
  138.             result = specSize;             
  139.         }else if (specMode == MeasureSpec.EXACTLY){             
  140.             // If your control can fit within these bounds return that value.              
  141. //            result = specSize;             
  142.         }       
  143.         return result;              
  144.     }  
  145.       
  146.     private void initHeight()  
  147.     {  
  148.         //设置 CY TextView的初始高度为0  
  149.         m_iTextHeight=0;  
  150.           
  151.         //大概计算 CY TextView所需高度  
  152.         FontMetrics fm = mPaint.getFontMetrics();          
  153.         int m_iFontHeight = (int) Math.ceil(fm.descent - fm.top) + (int)LineSpace;  
  154.         int line=0;  
  155.         int istart=0;  
  156.           
  157.         int w=0;  
  158.         for (int i = 0; i < string.length(); i++)  
  159.         {  
  160.             char ch = string.charAt(i);  
  161.             float[] widths = new float[1];  
  162.             String srt = String.valueOf(ch);  
  163.             mPaint.getTextWidths(srt, widths);  
  164.   
  165.             if (ch == '\n'){  
  166.                 line++;  
  167.                 istart = i + 1;  
  168.                 w = 0;  
  169.             }else{  
  170.                 w += (int) (Math.ceil(widths[0]));  
  171.                 if (w > m_iTextWidth){  
  172.                     line++;  
  173.                     istart = i;  
  174.                     i--;  
  175.                     w = 0;  
  176.                 }else{  
  177.                     if (i == (string.length() - 1)){  
  178.                         line++;  
  179.                     }  
  180.                 }  
  181.             }  
  182.         }  
  183.         m_iTextHeight=(line)*m_iFontHeight+2;  
  184.     }  
  185.                    
  186.     private int measureWidth(int measureSpec)   
  187.     {    
  188.         int specMode = MeasureSpec.getMode(measureSpec);             
  189.         int specSize = MeasureSpec.getSize(measureSpec);               
  190.   
  191.         // Default size if no limits are specified.            
  192.         int result = 500;            
  193.         if (specMode == MeasureSpec.AT_MOST){            
  194.             // Calculate the ideal size of your control             
  195.             // within this maximum size.           
  196.             // If your control fills the available space           
  197.             // return the outer bound.           
  198.             result = specSize;            
  199.         }else if (specMode == MeasureSpec.EXACTLY){             
  200.             // If your control can fit within these bounds return that value.             
  201.             result = specSize;              
  202.         }             
  203.         return result;            
  204.     }  
  205.       
  206.     public void SetText(String text)  
  207.     {  
  208.         string = text;  
  209.        // requestLayout();  
  210.        // invalidate();  
  211.     }     
  212. }   


 

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

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

[html]  view plain copy
  1. <resources>  
  2. <attr name="textwidth" format="integer"/>  
  3. <attr name="typeface">  
  4. <enum name="normal" value="0"/>  
  5. <enum name="sans" value="1"/>  
  6. <enum name="serif" value="2"/>  
  7. <enum name="monospace" value="3"/>  
  8. </attr>  
  9.   
  10. <declare-styleable name="CYTextView">   
  11. <attr name="textwidth" />   
  12. <attr name="textSize" format="dimension"/>  
  13. <attr name="textColor" format="reference|color"/>  
  14. <attr name="lineSpacingExtra" format="dimension"/>  
  15. <attr name="typeface" />  
  16. </declare-styleable>  
  17. </resources>   


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

[html]  view plain copy
  1. <?xml version="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]  view plain copy
  1. public class Main extends Activity {  
  2. CYTextView mCYTextView;  
  3. String text = "Android提供了精巧和有力的组件化模型构建用户的UI部分。主要是基于布局类:View和 ViewGroup。在此基础上,android平台提供了大量的预制的View和xxxViewGroup子 类,即布局(layout)和窗口小部件(widget)。可以用它们构建自己的UI。";  
  4.   
  5. /** Called when the activity is first created. */  
  6. @Override  
  7. public void onCreate(Bundle savedInstanceState) {  
  8. super.onCreate(savedInstanceState);  
  9. this.setContentView(R.layout.main);  
  10.   
  11. mCYTextView = (CYTextView)findViewById(R.id.mv);  
  12. mCYTextView.SetText(text);  
  13. }  
  14.   
  15. }   
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值