当前位置:   article > 正文

Android TextView 自动换行问题_textview中英文换行

textview中英文换行

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

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

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

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

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

1)修改Android源代码;将frameworks/base/core/java/android/text下的StaticLayout.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. }


 

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

2)自定义View显示文本

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

自定义View的步骤:

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

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

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

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

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


 

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

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

  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. <declare-styleable name="CYTextView">
  10. <attr name="textwidth" />
  11. <attr name="textSize" format="dimension"/>
  12. <attr name="textColor" format="reference|color"/>
  13. <attr name="lineSpacingExtra" format="dimension"/>
  14. <attr name="typeface" />
  15. </declare-styleable>
  16. </resources>


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

  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=============================

  1. public class Main extends Activity {
  2. CYTextView mCYTextView;
  3. String text = "Android提供了精巧和有力的组件化模型构建用户的UI部分。主要是基于布局类:View和 ViewGroup。在此基础上,android平台提供了大量的预制的View和xxxViewGroup子 类,即布局(layout)和窗口小部件(widget)。可以用它们构建自己的UI。";
  4. /** Called when the activity is first created. */
  5. @Override
  6. public void onCreate(Bundle savedInstanceState) {
  7. super.onCreate(savedInstanceState);
  8. this.setContentView(R.layout.main);
  9. mCYTextView = (CYTextView)findViewById(R.id.mv);
  10. mCYTextView.SetText(text);
  11. }
  12. }


 了解更多资讯请关注微信:caaz01

转自:http://hi.baidu.com/java_rose/blog/item/2940a030d1ec7f3e96ddd847.html

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/Cpp五条/article/detail/242880
推荐阅读
相关标签
  

闽ICP备14008679号