当前位置:   article > 正文

Android自定义TextView排版优化_android 开发中textview 文字排版的优化

android 开发中textview 文字排版的优化

今天的文章关于android中最常用的的控件Textview,安卓中的TextView在文字布局的时候会在每行的末尾进行智能的换行分割,特别是有标点符号等出现的时候。这个规律是怎样的我至今还没有探究过。有兴趣的大家可以自己去看一下TextView的源码。项目中需要对文字进行较舒服的排布,去掉尾部的空缺,所以我对此给出来自己的解决方案,先看效果图吧。


绿色字体是用自定义的TextView加载的文字信息,没有限制最大行数。白色文字是用android系统的TextView。黄色文字是自定义的TextView,限制了最大行数,并且设置了显示自定义省略信息,就是在布局文件中调用android:ellipsize="end"。效果还是很明显的

我这里就简单粗暴的去重写Textview的onDraw方法了,而且没有super,完全是自己用Canvas去绘画每一个文字或者符号。所以一定程度上讲,这更像是一个View,丢失了很多TextView的特性,当然为了保留更多的Textview的特性,我也在里面重写了很多方法,新加入了一些方法。代码给出来,大家可以根据自己的需要自己去拓展。有很多原来TextView的函数都失去了作用,使用的时候请注意。

  1. import android.app.Activity;
  2. import android.content.Context;
  3. import android.graphics.Canvas;
  4. import android.graphics.Color;
  5. import android.graphics.Paint;
  6. import android.util.AttributeSet;
  7. import android.widget.TextView;
  8. /**
  9. * 自定义的文字整齐排版Textview控件,能让文字相对更加的整齐
  10. * <p>
  11. * 在xml布局文件中请加入命名空间"http://hdt.hdt/hdt"用于设置以下属性(单数字不填单位):
  12. * lineSpacingExtra,textSize,paddingLeft,paddingRight。 宽度请设置充满父布局, 目前只支持结尾省略...
  13. *
  14. * @author illidan.huang 杭州
  15. */
  16. public class MyTextView extends TextView {
  17. private final String namespace = "http://hdt.hdt/hdt";
  18. private String text;
  19. private float textSize;
  20. private Paint paint1 = new Paint();
  21. private float paddingLeft;
  22. private float paddingRight;
  23. private float textShowWidth;
  24. private int textColor;
  25. private float lineSpace;
  26. private int maxLines = Integer.MAX_VALUE;
  27. private boolean ellipsize = false;
  28. private float ellipsizeLength = 0;
  29. private String ellipsizeString = "(未完待续...)";
  30. // 初始化是否需要设置高度,不加判断则会无限的递归onDraw,自己看
  31. private boolean needHieght = true;
  32. private int lineCount = 0;
  33. public MyTextView(Context context, AttributeSet attrs) {
  34. super(context, attrs);
  35. // TODO Auto-generated constructor stub
  36. text = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "text");
  37. textSize = attrs.getAttributeIntValue(namespace, "textSize", 10);
  38. textColor = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "textColor", Color.WHITE);
  39. maxLines = attrs.getAttributeIntValue("http://schemas.android.com/apk/res/android", "maxLines", Integer.MAX_VALUE);
  40. String ell = attrs.getAttributeValue("http://schemas.android.com/apk/res/android", "ellipsize");
  41. ellipsize = "3".equals(ell);//android:ellipsize="end"对应的值是3,请看安卓源码
  42. paddingLeft = attrs.getAttributeIntValue(namespace, "paddingLeft", 0);
  43. paddingRight = attrs.getAttributeIntValue(namespace, "paddingRight", 0);
  44. lineSpace = attrs.getAttributeIntValue(namespace, "lineSpacingExtra", 3);
  45. float d = context.getResources().getDisplayMetrics().density;
  46. textSize = d * textSize + 0.5f;
  47. lineSpace = d * lineSpace + 0.5f;
  48. if(maxLines <= 0){
  49. maxLines = Integer.MAX_VALUE;
  50. }
  51. paint1.setTextSize(textSize);
  52. paint1.setColor(textColor);
  53. paint1.setAntiAlias(true);
  54. textShowWidth = ((Activity) context).getWindowManager().getDefaultDisplay().getWidth() - paddingLeft - paddingRight;
  55. ellipsizeLength = paint1.measureText(ellipsizeString);
  56. }
  57. @Override
  58. protected void onDraw(Canvas canvas) {
  59. int lineCount = 0;
  60. char[] textCharArray = text.toCharArray();
  61. float drawedWidth = 0;
  62. float charWidth;
  63. for (int i = 0; i < textCharArray.length; i++) {
  64. charWidth = paint1.measureText(textCharArray, i, 1);
  65. // 这里是用于,设置了最大行数和末尾省略的情况下进行的判断,16完全是我凭感觉给出的数字,没有为什么
  66. if (ellipsize && textShowWidth - drawedWidth - ellipsizeLength < 16) {
  67. if (lineCount == maxLines - 1) {
  68. canvas.drawText(ellipsizeString, paddingLeft + drawedWidth, (lineCount + 1) * textSize + lineSpace
  69. * lineCount, paint1);
  70. break;
  71. }
  72. }
  73. // 跳入下一行判断
  74. if (textShowWidth - drawedWidth < charWidth || textCharArray[i] == '\n') {
  75. lineCount++;
  76. if (lineCount > maxLines - 1) {
  77. lineCount--;
  78. break;
  79. }
  80. drawedWidth = 0;
  81. }
  82. canvas.drawText(textCharArray, i, 1, paddingLeft + drawedWidth, (lineCount + 1) * textSize + lineSpace * lineCount,
  83. paint1);
  84. drawedWidth += charWidth;
  85. }
  86. if (needHieght) {
  87. setHeight((lineCount + 1) * (int) (textSize + lineSpace));
  88. needHieght = false;
  89. }
  90. this.lineCount = lineCount;
  91. }
  92. @Override
  93. public void invalidate() {
  94. needHieght = true;
  95. super.invalidate();
  96. }
  97. @Override
  98. public void setText(CharSequence text, BufferType type) {
  99. // TODO Auto-generated method stub
  100. super.setText(text, type);
  101. this.text = String.valueOf(text);
  102. invalidate();
  103. }
  104. /**
  105. * 设置省略显示内容,默认"。。。"
  106. *
  107. * @param ellString
  108. */
  109. public final void setEllipsizeString(String ellString) {
  110. this.ellipsizeString = ellString;
  111. }
  112. /**
  113. * 设置结尾是否显示省略内容
  114. *
  115. * @param isEnd
  116. */
  117. public final void setEllipsizeEnd(boolean isEnd) {
  118. this.ellipsize = isEnd;
  119. }
  120. @Override
  121. public void setMaxLines(int maxlines) {
  122. this.maxLines = maxlines;
  123. if(this.maxLines <= 0){
  124. this.maxLines = Integer.MAX_VALUE;
  125. }
  126. super.setMaxLines(maxlines);
  127. }
  128. @Override
  129. public CharSequence getText() {
  130. return this.text;
  131. }
  132. /**
  133. * 设置行间距
  134. *
  135. * @param spa
  136. */
  137. public void setLineSpacingExtra(float spa) {
  138. this.lineSpace = spa;
  139. }
  140. @Override
  141. public int getLineCount() {
  142. return lineCount;
  143. }
  144. @Override
  145. public int getLineHeight() {
  146. return (int) (textSize+lineSpace);
  147. }
  148. @Override
  149. public float getTextSize() {
  150. return textSize;
  151. }
  152. @Override
  153. public void setSingleLine() {
  154. setSingleLine(true);
  155. }
  156. @Override
  157. public void setSingleLine(boolean singleLine) {
  158. if(singleLine){
  159. setMaxLines(1);
  160. }else{
  161. setMaxLines(Integer.MAX_VALUE);
  162. }
  163. }
  164. @Override
  165. public void setTextColor(int color) {
  166. this.textColor = color;
  167. paint1.setColor(color);
  168. super.setTextColor(color);
  169. }
  170. }

英文的实现效果我这里暂时未考虑到,需要的话,我给个思路。就是在onDraw函数中,对文字进行分词的时候

char[] textCharArray = text.toCharArray(); 按单词为单位进行分割,而不是一个字符char。

以下是图示的布局文件


  1. <?xml version="1.0" encoding="utf-8"?>
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
  3.     xmlns:hdt="http://hdt.hdt/hdt"
  4.     android:layout_width="fill_parent"
  5.     android:layout_height="fill_parent"
  6.     android:background="@android:color/black"
  7.     android:gravity="center_horizontal"
  8.     android:orientation="vertical" >
  9.     <ScrollView
  10.         android:layout_width="wrap_content"
  11.         android:layout_height="wrap_content" >
  12.         <LinearLayout
  13.             android:layout_width="wrap_content"
  14.             android:layout_height="wrap_content"
  15.             android:orientation="vertical" >
  16.             <com.wigit.MyTextView
  17.                 android:id="@+id/txt1"
  18.                 android:layout_width="wrap_content"
  19.                 android:layout_height="wrap_content"
  20.                 hdt:paddingLeft="5"
  21.                 android:text="【一人之下,万人之上】《意林》卷一引《六韬》:“屈一人下,伸万人上,惟圣人能行之。”《汉书·萧何传》:“夫能诎於一人之下,而信於万乘之上者,汤武是也。”一人,谓天子;万人,谓百官。多指地位崇高权势显赫的大臣。【一人之交】好友;至交。谓亲密如一人。【一夫之用】谓仅能当一人之用,而无兼人之能。【一夫之勇】犹言匹夫之勇。"
  22.                 android:textColor="#FE8A08"
  23.                 hdt:lineSpacingExtra="3"
  24.                 hdt:textSize="16" 
  25.                 ></com.wigit.MyTextView>"
  26.             <TextView
  27.                 android:layout_width="wrap_content"
  28.                 android:layout_height="wrap_content"
  29.                 android:paddingLeft="5dp"
  30.                 android:paddingRight="5dp"
  31.                 android:text="【一人之下,万人之上】《意林》卷一引《六韬》:“屈一人下,伸万人上,惟圣人能行之。”《汉书·萧何传》:“夫能诎於一人之下,而信於万乘之上者,汤武是也。”一人,谓天子;万人,谓百官。多指地位崇高权势显赫的大臣。【一人之交】好友;至交。谓亲密如一人。【一夫之用】谓仅能当一人之用,而无兼人之能。【一夫之勇】犹言匹夫之勇。"
  32.                 android:textColor="@android:color/white"
  33.                 android:textSize="16dp" />
  34.             
  35.             <com.wigit.MyTextView
  36.                 android:id="@+id/txt1"
  37.                 android:layout_width="wrap_content"
  38.                 android:layout_height="wrap_content"
  39.                 hdt:paddingLeft="5"
  40.                 android:text="【一人之下,万人之上】《意林》卷一引《六韬》:“屈一人下,伸万人上,惟圣人能行之。”《汉书·萧何传》:“夫能诎於一人之下,而信於万乘之上者,汤武是也。”一人,谓天子;万人,谓百官。多指地位崇高权势显赫的大臣。【一人之交】好友;至交。谓亲密如一人。【一夫之用】谓仅能当一人之用,而无兼人之能。【一夫之勇】犹言匹夫之勇。"
  41.                 android:textColor="#FE8A08"
  42.                 hdt:lineSpacingExtra="3"
  43.                 hdt:textSize="16" 
  44.                 android:maxLines="5"
  45.                 android:ellipsize="end"
  46.                 ></com.wigit.MyTextView>"
  47.         </LinearLayout>
  48.     </ScrollView>
  49. </LinearLayout>

若有疑问请下面留言。

若有不足请留言或者联系我,hdtpjhz@163.com


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

闽ICP备14008679号