适应多行长文本的Android TextView

来源:互联网 发布:数据采集与控制系统 编辑:程序博客网 时间:2024/04/30 18:03

http://blog.csdn.net/hellogv/article/details/7562315


 大家经常会用到系统默认的TextView,TextView可以很好地适应单行长文本(尾部自动打上省略号),以及可以完整显示多行文本(TextView的宽高足够大)。但如果是很多行的文本而TextView又足够大的时候,则会出现以下这种情况.......超出的文本受TextView大小限制,不能完全显示。

      本文主要实现一个能够适应多行长文本的TextView,自动缩减长文本并在结尾补上省略号。如下图:红色部分为普通的TextView,绿色部分为本文实现的TextView。

 
       本文的源码可以到 http://download.csdn.net/detail/hellogv/4298631 下载,本文的TextViewMultilineEllipse.java改自http://code.google.com/p/android-textview-multiline-ellipse/以及http://code.google.com/p/android/的MyClipTextView.java,相对于前面2者,本文使用哈希表来保存每次onMeasure()计算所得的宽高,大幅减少重复计算宽高。

 

本文的主Activity的源码如下:

[java] view plaincopyprint?
  1. public class AutoFixTextViewActivity extends Activity {  
  2.     private LinearLayout linearLayout1;  
  3.     private TextViewMultilineEllipse tvMultilineEllipse;  
  4.     private TextView tvNormal;  
  5.       
  6.     //水调歌头,大家懂的  
  7.     private final String text="明月几时有?把酒问青天。不知天上宫阙,今夕是何年。\n"  
  8.             +"我欲乘风归去,又恐琼楼玉宇,高处不胜寒。\n"  
  9.             +"起舞弄清影,何似在人间。\n"  
  10.             +"转朱阁,低绮户,照无眠。不应有恨,何事长向别时圆?\n"  
  11.             +"人有悲欢离合,月有阴晴圆缺,此事古难全。\n"  
  12.             +"但愿人长久,千里共婵娟。";  
  13.     @Override  
  14.     public void onCreate(Bundle savedInstanceState) {  
  15.         super.onCreate(savedInstanceState);  
  16.         setContentView(R.layout.main);  
  17.         this.setTitle("适应多行文本的Android TextView---hellogv");  
  18.           
  19.         //共同的宽高  
  20.         LayoutParams lp=new LayoutParams(LayoutParams.FILL_PARENT,100);  
  21.         //----用TextView来显示换行长文本----//  
  22.         tvNormal=(TextView)this.findViewById(R.id.tvNormal);  
  23.         tvNormal.setLayoutParams(lp); //限制TextView的宽高  
  24.         tvNormal.setEllipsize(TextUtils.TruncateAt.END);  
  25.         tvNormal.setSingleLine(false);  
  26.         tvNormal.setMaxLines(5);  
  27.         tvNormal.setText(text);  
  28.           
  29.           
  30.         //----用TextViewMultilineEllipse来显示换行长文本----//  
  31.         linearLayout1=(LinearLayout) this.findViewById(R.id.linearLayout1);  
  32.           
  33.         tvMultilineEllipse = new TextViewMultilineEllipse(this);  
  34.         tvMultilineEllipse.setLayoutParams(lp);//限制TextView的宽高  
  35.         tvMultilineEllipse.setEllipsis("...");//...替换剩余字符串  
  36.         tvMultilineEllipse.setMaxLines(5);  
  37.         tvMultilineEllipse.setTextSize((int)tvNormal.getTextSize());//设置文字大小  
  38.         tvMultilineEllipse.setTextColor(Color.WHITE);  
  39.         tvMultilineEllipse.setText(text);//设置文本  
  40.           
  41.         //在代码里添加tvMultilineEllipse,暂时不支持Layout里直接添加  
  42.         linearLayout1.addView(tvMultilineEllipse);  
  43.           
  44.     }  
  45.    
  46.       
  47. }  


PS:TextViewMultilineEllipse是在代码里动态构建和使用,而不能直接在Layout.xml里使用。

main.xml的源码如下:

 

[html] view plaincopyprint?
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"  
  3.     android:layout_width="fill_parent"  
  4.     android:layout_height="fill_parent"  
  5.     android:orientation="vertical" >  
  6.   
  7.     <TextView  
  8.         android:id="@+id/tvNormal"  
  9.         android:layout_width="wrap_content"  
  10.         android:layout_height="wrap_content"  
  11.         android:text="Medium Text"  
  12.         android:textAppearance="?android:attr/textAppearanceMedium" />  
  13.   
  14.     <LinearLayout  
  15.         android:id="@+id/linearLayout1"  
  16.         android:layout_width="match_parent"  
  17.         android:layout_height="wrap_content"  
  18.         android:layout_marginTop="20dip" >  
  19.     </LinearLayout>  
  20.   
  21. </LinearLayout>  


TextViewMultilineEllipse.java源码如下,有点多,读者可以直接忽略:

[java] view plaincopyprint?
  1. public class TextViewMultilineEllipse extends TextView{  
  2.   
  3.     private TextPaint mTextPaint;  
  4.     private String mText;  
  5.     private int mAscent;  
  6.     private String mStrEllipsis;  
  7.     private String mStrEllipsisMore;  
  8.     private int mMaxLines;  
  9.     private boolean mDrawEllipsizeMoreString;  
  10.     private int mColorEllipsizeMore;  
  11.     private boolean mRightAlignEllipsizeMoreString;  
  12.     private boolean mExpanded;  
  13.     private LineBreaker mBreakerExpanded;  
  14.     private LineBreaker mBreakerCollapsed;  
  15.     /**hashMapW是优化的关键点,通过哈希表来减少计算次数*/  
  16.     private HashMap<Integer,Integer> hashMapW=new HashMap<Integer,Integer>();  
  17.     public TextViewMultilineEllipse(Context context) {  
  18.         super(context);  
  19.      // TODO Auto-generated constructor stub  
  20.         mExpanded = false;  
  21.         mDrawEllipsizeMoreString = true;  
  22.         mRightAlignEllipsizeMoreString = false;  
  23.         mMaxLines = -1;  
  24.         mStrEllipsis = "...";  
  25.         mStrEllipsisMore = "";  
  26.         mColorEllipsizeMore = 0xFF0000FF;  
  27.           
  28.         mBreakerExpanded = new LineBreaker();          
  29.         mBreakerCollapsed = new LineBreaker();  
  30.           
  31.         // Default font size and color.  
  32.         mTextPaint = new TextPaint();  
  33.         mTextPaint.setAntiAlias(true);  
  34.         mTextPaint.setTextSize(13);  
  35.         mTextPaint.setColor(0xFF000000);  
  36.         mTextPaint.setTextAlign(Align.LEFT);  
  37.         setDrawingCacheEnabled(true);  
  38.     }  
  39.       
  40.     /** 
  41.      * Sets the text to display in this widget. 
  42.      * @param text The text to display. 
  43.      */  
  44.     public void setText(String text) {  
  45.         mText = text;  
  46.         requestLayout();  
  47.         invalidate();  
  48.     }  
  49.   
  50.     /** 
  51.      * Sets the text size for this widget. 
  52.      * @param size Font size. 
  53.      */  
  54.     public void setTextSize(int size) {  
  55.         mTextPaint.setTextSize(size);  
  56.         requestLayout();  
  57.         invalidate();  
  58.     }  
  59.   
  60.     /** 
  61.      * Sets the text color for this widget. 
  62.      * @param color ARGB value for the text. 
  63.      */  
  64.     public void setTextColor(int color) {  
  65.         mTextPaint.setColor(color);  
  66.         invalidate();  
  67.     }  
  68.   
  69.     /** 
  70.      * The string to append when ellipsizing. Must be shorter than the available 
  71.      * width for a single line! 
  72.      * @param ellipsis The ellipsis string to use, like "...", or "-----". 
  73.      */  
  74.     public void setEllipsis(String ellipsis) {  
  75.         mStrEllipsis = ellipsis;  
  76.     }  
  77.       
  78.     /** 
  79.      * Optional extra ellipsize string. This 
  80.      * @param ellipsisMore 
  81.      */  
  82.     public void setEllipsisMore(String ellipsisMore) {  
  83.         mStrEllipsisMore = ellipsisMore;  
  84.     }  
  85.       
  86.     /** 
  87.      * The maximum number of lines to allow, height-wise. 
  88.      * @param maxLines 
  89.      */  
  90.     public void setMaxLines(int maxLines) {  
  91.         mMaxLines = maxLines;  
  92.     }  
  93.       
  94.     /** 
  95.      * Turn drawing of the optional ellipsizeMore string on or off. 
  96.      * @param drawEllipsizeMoreString Yes or no. 
  97.      */  
  98.     public void setDrawEllipsizeMoreString(boolean drawEllipsizeMoreString) {  
  99.         mDrawEllipsizeMoreString = drawEllipsizeMoreString;  
  100.     }  
  101.       
  102.     /** 
  103.      * Font color to use for the optional ellipsizeMore string. 
  104.      * @param color ARGB color. 
  105.      */  
  106.     public void setColorEllpsizeMore(int color) {  
  107.         mColorEllipsizeMore = color;  
  108.     }  
  109.       
  110.     /** 
  111.      * When drawing the ellipsizeMore string, either draw it wherever ellipsizing on the last 
  112.      * line occurs, or always right align it. On by default. 
  113.      * @param rightAlignEllipsizeMoreString Yes or no. 
  114.      */  
  115.     public void setRightAlignEllipsizeMoreString(boolean rightAlignEllipsizeMoreString) {  
  116.         mRightAlignEllipsizeMoreString = rightAlignEllipsizeMoreString;  
  117.     }  
  118.       
  119.     /** 
  120.      * @see android.view.View#measure(int, int) 
  121.      */  
  122.     @Override  
  123.     protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {  
  124.         setMeasuredDimension(  
  125.             measureWidth(widthMeasureSpec),  
  126.             measureHeight(heightMeasureSpec));  
  127.     }  
  128.   
  129.     /** 
  130.      * Determines the width of this view 
  131.      * @param measureSpec A measureSpec packed into an int 
  132.      * @return The width of the view, honoring constraints from measureSpec 
  133.      */  
  134.     private int measureWidth(int measureSpec) {  
  135.         int result = 0;  
  136.         int specMode = MeasureSpec.getMode(measureSpec);  
  137.         int specSize = MeasureSpec.getSize(measureSpec);  
  138.   
  139.         if (specMode == MeasureSpec.EXACTLY) {  
  140.             // We were told how big to be.  
  141.             result = specSize;  
  142.               
  143.             // Format the text using this exact width, and the current mode.  
  144.             breakWidth(specSize);  
  145.         }   
  146.         else {  
  147.             if (specMode == MeasureSpec.AT_MOST) {  
  148.                 // Use the AT_MOST size - if we had very short text, we may need even less  
  149.                 // than the AT_MOST value, so return the minimum.  
  150.                 result = breakWidth(specSize);  
  151.                 result = Math.min(result, specSize);  
  152.             }  
  153.             else {  
  154.                 // We're not given any width - so in this case we assume we have an unlimited  
  155.                 // width?  
  156.                 breakWidth(specSize);  
  157.             }  
  158.         }  
  159.   
  160.         return result;  
  161.     }  
  162.   
  163.     /** 
  164.      * Determines the height of this view 
  165.      * @param measureSpec A measureSpec packed into an int 
  166.      * @return The height of the view, honoring constraints from measureSpec 
  167.      */  
  168.     private int measureHeight(int measureSpec) {  
  169.         int result = 0;  
  170.         int specMode = MeasureSpec.getMode(measureSpec);  
  171.         int specSize = MeasureSpec.getSize(measureSpec);  
  172.   
  173.         mAscent = (int) mTextPaint.ascent();  
  174.         if (specMode == MeasureSpec.EXACTLY) {  
  175.             // We were told how big to be, so nothing to do.  
  176.             result = specSize;  
  177.         }   
  178.         else {  
  179.             // The lines should already be broken up. Calculate our max desired height  
  180.             // for our current mode.  
  181.             int numLines;  
  182.             if (mExpanded) {  
  183.                 numLines = mBreakerExpanded.getLines().size();  
  184.             }  
  185.             else {  
  186.                 numLines = mBreakerCollapsed.getLines().size();  
  187.             }  
  188.             result = numLines * (int) (-mAscent + mTextPaint.descent())  
  189.                    + getPaddingTop()  
  190.                    + getPaddingBottom();  
  191.   
  192.             // Respect AT_MOST value if that was what is called for by measureSpec.  
  193.             if (specMode == MeasureSpec.AT_MOST) {  
  194.                 result = Math.min(result, specSize);  
  195.             }  
  196.         }  
  197.         return result;  
  198.     }  
  199.   
  200.     /** 
  201.      * Render the text 
  202.      *  
  203.      * @see android.view.View#onDraw(android.graphics.Canvas) 
  204.      */  
  205.     @Override  
  206.     protected void onDraw(Canvas canvas) {  
  207.         super.onDraw(canvas);  
  208.         List<int[]> lines;  
  209.         LineBreaker breaker;  
  210.         if (mExpanded) {  
  211.             breaker = mBreakerExpanded;  
  212.             lines = mBreakerExpanded.getLines();  
  213.         }  
  214.         else {  
  215.             breaker = mBreakerCollapsed;  
  216.             lines = mBreakerCollapsed.getLines();  
  217.         }  
  218.           
  219.         float x = getPaddingLeft();  
  220.         float y = getPaddingTop() + (-mAscent);  
  221.         for (int i = 0; i < lines.size(); i++) {  
  222.             // Draw the current line.  
  223.             int[] pair = lines.get(i);  
  224.             canvas.drawText(mText, pair[0], pair[1]+1, x, y, mTextPaint);  
  225.               
  226.             // Draw the ellipsis if necessary.  
  227.             if (i == lines.size() - 1) {  
  228.                 if (breaker.getRequiredEllipsis()) {  
  229.                     canvas.drawText(mStrEllipsis, x + breaker.getLengthLastEllipsizedLine(), y, mTextPaint);  
  230.                     if (mDrawEllipsizeMoreString) {  
  231.                         int lastColor = mTextPaint.getColor();  
  232.                         mTextPaint.setColor(mColorEllipsizeMore);  
  233.                         if (mRightAlignEllipsizeMoreString) {  
  234.                             // Seems to not be right...  
  235.                             canvas.drawText(mStrEllipsisMore, canvas.getWidth()-(breaker.getLengthEllipsisMore()+getPaddingRight()+getPaddingLeft()), y, mTextPaint);  
  236.                         }  
  237.                         else {  
  238.                             canvas.drawText(mStrEllipsisMore, x + breaker.getLengthLastEllipsizedLinePlusEllipsis(), y, mTextPaint);  
  239.                         }  
  240.                         mTextPaint.setColor(lastColor);  
  241.                     }  
  242.                 }  
  243.             }  
  244.               
  245.             y += (-mAscent + mTextPaint.descent());  
  246.             if (y > canvas.getHeight()) {  
  247.                 break;  
  248.             }  
  249.         }  
  250.     }  
  251.       
  252.     public boolean getIsExpanded() {  
  253.         return mExpanded;  
  254.     }  
  255.       
  256.     public void expand() {  
  257.         mExpanded = true;  
  258.         requestLayout();  
  259.         invalidate();  
  260.     }  
  261.       
  262.     public void collapse() {  
  263.         mExpanded = false;  
  264.         requestLayout();  
  265.         invalidate();  
  266.     }  
  267.       
  268.   
  269.     private int breakWidth(int availableWidth) {  
  270.         if(hashMapW.containsKey(availableWidth))  
  271.             return hashMapW.get(availableWidth);  
  272.           
  273.         int widthUsed = 0;  
  274.         if (mExpanded) {  
  275.             widthUsed =  
  276.               mBreakerExpanded.breakText(  
  277.                  mText,   
  278.                 availableWidth - getPaddingLeft() - getPaddingRight(),   
  279.                 mTextPaint);  
  280.         }  
  281.         else {  
  282.             widthUsed =  
  283.               mBreakerCollapsed.breakText(  
  284.                 mText,   
  285.                 mStrEllipsis,   
  286.                 mStrEllipsisMore,   
  287.                 mMaxLines,   
  288.                 availableWidth - getPaddingLeft() - getPaddingRight(),   
  289.                 mTextPaint);  
  290.         }  
  291.         hashMapW.put(availableWidth, widthUsed + getPaddingLeft() + getPaddingRight());  
  292.         return widthUsed + getPaddingLeft() + getPaddingRight();  
  293.     }  
  294.       
  295.       
  296.     /** 
  297.      * Used internally to break a string into a list of integer pairs. The pairs are 
  298.      * start and end locations for lines given the current available layout width. 
  299.      */  
  300.     private static class LineBreaker  
  301.     {  
  302.         /** Was the input text long enough to need an ellipsis? */  
  303.         private boolean mRequiredEllipsis;  
  304.           
  305.         /** Beginning and end indices for the input string. */  
  306.         private ArrayList<int[]> mLines;  
  307.           
  308.         /** The width in pixels of the last line, used to draw the ellipsis if necessary. */  
  309.         private float mLengthLastLine;  
  310.           
  311.         /** The width of the ellipsis string, so we know where to draw the ellipsisMore string 
  312.          *  if necessary. 
  313.          */  
  314.         private float mLengthEllipsis;  
  315.           
  316.         /** The width of the ellipsizeMore string, same use as above. */  
  317.         private float mLengthEllipsisMore;  
  318.           
  319.           
  320.         public LineBreaker() {  
  321.             mRequiredEllipsis = false;  
  322.             mLines = new ArrayList<int[]>();  
  323.         }  
  324.   
  325.         /** 
  326.          * Used for breaking text in 'expanded' mode, which needs no ellipse. 
  327.          * Uses as many lines as is necessary to accomodate the entire input 
  328.          * string. 
  329.          * @param input String to be broken. 
  330.          * @param maxWidth Available layout width. 
  331.          * @param tp Current paint object with styles applied to it. 
  332.          */  
  333.         public int breakText(String input,   
  334.                                 int maxWidth,   
  335.                              TextPaint tp)   
  336.         {  
  337.             return breakText(input, nullnull, -1, maxWidth, tp);  
  338.         }  
  339.   
  340.         /** 
  341.          * Used for breaking text, honors ellipsizing. The string will be broken into lines using 
  342.          * the available width. The last line will subtract the physical width of the ellipsis 
  343.          * string from maxWidth to reserve room for the ellipsis. If the ellpsisMore string is set, 
  344.          * then space will also be reserved for its length as well. 
  345.          * @param input String to be broken. 
  346.          * @param ellipsis Ellipsis string, like "..." 
  347.          * @param ellipsisMore Optional space reservation after the ellipsis, like " Read More!" 
  348.          * @param maxLines Max number of lines to allow before ellipsizing. 
  349.          * @param maxWidth Available layout width. 
  350.          * @param tp Current paint object with styles applied to it. 
  351.          */  
  352.         public int breakText(String input,   
  353.                                 String ellipsis,  
  354.                                 String ellipsisMore,  
  355.                              int maxLines,   
  356.                              int maxWidth,   
  357.                              TextPaint tp)   
  358.         {  
  359.             mLines.clear();  
  360.             mRequiredEllipsis = false;  
  361.             mLengthLastLine = 0.0f;  
  362.             mLengthEllipsis = 0.0f;  
  363.             mLengthEllipsisMore = 0.0f;  
  364.               
  365.             // If maxWidth is -1, interpret that as meaning to render the string on a single  
  366.             // line. Skip everything.  
  367.             if (maxWidth == -1) {  
  368.                 mLines.add(new int[]{ 0, input.length() });  
  369.                 return (int)(tp.measureText(input) + 0.5f);  
  370.             }  
  371.   
  372.             // Measure the ellipsis string, and the ellipsisMore string if valid.  
  373.             if (ellipsis != null) {  
  374.                 mLengthEllipsis = tp.measureText(ellipsis);  
  375.             }  
  376.             if (ellipsisMore != null) {  
  377.                 mLengthEllipsisMore = tp.measureText(ellipsisMore);  
  378.             }  
  379.   
  380.             // Start breaking.  
  381.             int posStartThisLine = -1;  
  382.             float lengthThisLine = 0.0f;  
  383.             boolean breakWords = true;  
  384.             int pos = 0;  
  385.             while (pos < input.length()) {  
  386.                   
  387.                 if (posStartThisLine == -1) {  
  388.                     posStartThisLine = pos;  
  389.                 }  
  390.                   
  391.                 if (mLines.size() == maxLines) {  
  392.                     mRequiredEllipsis = true;  
  393.                     break;  
  394.                 }  
  395.                   
  396.                 float widthOfChar = tp.measureText(input.charAt(pos) + "");  
  397.                 boolean newLineRequired = false;  
  398.                   
  399.                 if(!hasChinese(input)){/**english*/  
  400.                     // Check for a new line character or if we've run over max width.  
  401.                     if (input.charAt(pos) == '\n') {  
  402.                         newLineRequired = true;  
  403.                           
  404.                         // We want the current line to go up to the character right before the  
  405.                         // new line char, and we want the next line to start at the char after  
  406.                         // this new line char.  
  407.                         mLines.add(new int[] { posStartThisLine, pos-1 });  
  408.                     }else if (lengthThisLine + widthOfChar >= maxWidth) {  
  409.                         newLineRequired = true;  
  410.                         // We need to backup if we are in the middle of a word.  
  411.                         if (input.charAt(pos) == ' ' || breakWords == false) {  
  412.                             // Backup one character, because it doesn't fit on this line.  
  413.                             pos--;  
  414.                               
  415.                             // So this line includes up to the character before the space.  
  416.                             mLines.add(new int[] { posStartThisLine, pos });  
  417.                         }else {  
  418.                             // Backup until we are at a space.  
  419.                             Log.v("*******""*********************************now char = " + input.charAt(pos));  
  420.                             while (input.charAt(pos) != ' ') {  
  421.                                 pos--;  
  422.                             }  
  423.                               
  424.                             // This line includes up to the space.  
  425.                             mLines.add(new int[] { posStartThisLine, pos });  
  426.                         }  
  427.                     }  
  428.                 }else{/**chinese*/  
  429.                     // Check for a new line character or if we've run over max width.  
  430.                     if (input.charAt(pos) == '\n') {  
  431.                         newLineRequired = true;  
  432.                           
  433.                         // We want the current line to go up to the character right before the  
  434.                         // new line char, and we want the next line to start at the char after  
  435.                         // this new line char.  
  436.                         mLines.add(new int[] { posStartThisLine, pos-1 });  
  437.                     }else if (lengthThisLine + widthOfChar >= maxWidth) {  
  438.                         newLineRequired = true;  
  439.                             // This line includes up to the space.  
  440.                             mLines.add(new int[] { posStartThisLine, pos });  
  441.                     }  
  442.                 }  
  443.                   
  444.                   
  445.                 if (newLineRequired) {  
  446.                     // The next cycle should reset the position if it sees it's -1 (to whatever i is).  
  447.                     posStartThisLine = -1;  
  448.                       
  449.                     // Reset line length for next iteration.  
  450.                     lengthThisLine = 0.0f;  
  451.                       
  452.                     // When we get to the last line, subtract the width of the ellipsis.  
  453.                     if (mLines.size() == maxLines - 1) {  
  454.                         maxWidth -= (mLengthEllipsis + mLengthEllipsisMore);  
  455.                         // We also don't need to break on a full word, it'll look a little  
  456.                         // cleaner if all breaks on the final lines break in the middle of  
  457.                         // the last word.  
  458.                         breakWords = false;  
  459.                     }  
  460.                 }else {  
  461.                     if(!hasChinese(input)){/**english*/  
  462.                         lengthThisLine += widthOfChar;  
  463.                     }else{/**chinese*/  
  464.                         lengthThisLine += (widthOfChar + 0.5f);  
  465.                     }  
  466.                       
  467.                     // If we're on the last character of the input string, add on whatever we have leftover.  
  468.                     if (pos == input.length() - 1) {  
  469.                         mLines.add(new int[] { posStartThisLine, pos });  
  470.                     }  
  471.                 }  
  472.                   
  473.                 pos++;  
  474.             }  
  475.               
  476.             // If we ellipsized, then add the ellipsis string to the end.  
  477.             if (mRequiredEllipsis) {  
  478.                 int[] pairLast = mLines.get(mLines.size()-1);  
  479.                 mLengthLastLine = tp.measureText(input.substring(pairLast[0], pairLast[1] + 1));  
  480.             }  
  481.               
  482.             // If we required only one line, return its length, otherwise we used  
  483.             // whatever the maxWidth supplied was.  
  484.             if (mLines.size() == 0) {  
  485.                 return 0;  
  486.             }  
  487.             else if (mLines.size() == 1) {  
  488.                 return (int)(tp.measureText(input) + 0.5f);  
  489.             }  
  490.             else {  
  491.                 return maxWidth;  
  492.             }  
  493.         }  
  494.           
  495.         public boolean getRequiredEllipsis() {  
  496.             return mRequiredEllipsis;  
  497.         }  
  498.           
  499.         public List<int[]> getLines() {  
  500.             return mLines;  
  501.         }  
  502.           
  503.         public float getLengthLastEllipsizedLine() {  
  504.             return mLengthLastLine;  
  505.         }  
  506.           
  507.         public float getLengthLastEllipsizedLinePlusEllipsis() {  
  508.             return mLengthLastLine + mLengthEllipsis;  
  509.         }  
  510.           
  511.         public float getLengthEllipsis() {  
  512.             return mLengthEllipsis;  
  513.         }  
  514.           
  515.         public float getLengthEllipsisMore() {  
  516.             return mLengthEllipsisMore;  
  517.         }  
  518.           
  519.         /** 
  520.          * 判断文本中是否含有中文 
  521.          */  
  522.         private boolean hasChinese(String input){  
  523.             return input.getBytes().length != input.length();  
  524.         }  
  525.     }  
  526.   
  527. }