本文主要是介绍textview中有很多行,我只让它显示三行,最后显示...,我设置了android:maxLines=3和android:ellipsize=end,但出现的问题是只显示两行就显示“...”,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
http://topic.csdn.net/u/20110909/18/7734814e-caa2-4687-8aea-27d404d34f97.html
textview中有很多行,我只让它显示三行,最后显示...,我设置了android:maxLines="3"和android:ellipsize="end",但出现的问题是只显示两行就显示“...” :
<TextView
android:id="@+id/jgli_title"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@+id/jgli_pic"
android:layout_alignParentTop="true"
android:layout_marginTop="5dip"
android:layout_alignParentRight="true"
android:layout_marginRight="5dip"
android:maxLines="3"
android:ellipsize="end"
android:text="@+id/bb_price"
style="@style/listview_item_text"
/>
可以把android:ellipsize="end" 去掉,代码控制,也可以:
http://code.google.com/p/android/issues/detail?id=2254
http://code.google.com/p/android-textview-multiline-ellipse/source/checkout
package com.test;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.text.TextPaint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.View;
import android.view.View.MeasureSpec;import java.util.ArrayList;
import java.util.List;public class MyClipTextView extends View{private TextPaint mTextPaint;private String mText;private int mAscent;private String mStrEllipsis;private String mStrEllipsisMore;private int mMaxLines;private boolean mDrawEllipsizeMoreString;private int mColorEllipsizeMore;private boolean mRightAlignEllipsizeMoreString;private boolean mExpanded;private LineBreaker mBreakerExpanded;private LineBreaker mBreakerCollapsed;public MyClipTextView(Context context) {super(context);// TODO Auto-generated constructor stubmExpanded = false;mDrawEllipsizeMoreString = true;mRightAlignEllipsizeMoreString = false;mMaxLines = -1;mStrEllipsis = "...";mStrEllipsisMore = "";mColorEllipsizeMore = 0xFF0000FF;mBreakerExpanded = new LineBreaker(); mBreakerCollapsed = new LineBreaker();// Default font size and color.mTextPaint = new TextPaint();mTextPaint.setAntiAlias(true);mTextPaint.setTextSize(13);mTextPaint.setColor(0xFF000000);mTextPaint.setTextAlign(Align.LEFT);}/*** Sets the text to display in this widget.* @param text The text to display.*/public void setText(String text) {mText = text;requestLayout();invalidate();}/*** Sets the text size for this widget.* @param size Font size.*/public void setTextSize(int size) {mTextPaint.setTextSize(size);requestLayout();invalidate();}/*** Sets the text color for this widget.* @param color ARGB value for the text.*/public void setTextColor(int color) {mTextPaint.setColor(color);invalidate();}/*** The string to append when ellipsizing. Must be shorter than the available* width for a single line!* @param ellipsis The ellipsis string to use, like "...", or "-----".*/public void setEllipsis(String ellipsis) {mStrEllipsis = ellipsis;}/*** Optional extra ellipsize string. This* @param ellipsisMore*/public void setEllipsisMore(String ellipsisMore) {mStrEllipsisMore = ellipsisMore;}/*** The maximum number of lines to allow, height-wise.* @param maxLines*/public void setMaxLines(int maxLines) {mMaxLines = maxLines;}/*** Turn drawing of the optional ellipsizeMore string on or off.* @param drawEllipsizeMoreString Yes or no.*/public void setDrawEllipsizeMoreString(boolean drawEllipsizeMoreString) {mDrawEllipsizeMoreString = drawEllipsizeMoreString;}/*** Font color to use for the optional ellipsizeMore string.* @param color ARGB color.*/public void setColorEllpsizeMore(int color) {mColorEllipsizeMore = color;}/*** When drawing the ellipsizeMore string, either draw it wherever ellipsizing on the last* line occurs, or always right align it. On by default.* @param rightAlignEllipsizeMoreString Yes or no.*/public void setRightAlignEllipsizeMoreString(boolean rightAlignEllipsizeMoreString) {mRightAlignEllipsizeMoreString = rightAlignEllipsizeMoreString;}/*** @see android.view.View#measure(int, int)*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(measureWidth(widthMeasureSpec),measureHeight(heightMeasureSpec));}/*** Determines the width of this view* @param measureSpec A measureSpec packed into an int* @return The width of the view, honoring constraints from measureSpec*/private int measureWidth(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {// We were told how big to be.result = specSize;// Format the text using this exact width, and the current mode.breakWidth(specSize);} else {if (specMode == MeasureSpec.AT_MOST) {// Use the AT_MOST size - if we had very short text, we may need even less// than the AT_MOST value, so return the minimum.result = breakWidth(specSize);result = Math.min(result, specSize);}else {// We're not given any width - so in this case we assume we have an unlimited// width?breakWidth(specSize);}}return result;}/*** Determines the height of this view* @param measureSpec A measureSpec packed into an int* @return The height of the view, honoring constraints from measureSpec*/private int measureHeight(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);mAscent = (int) mTextPaint.ascent();if (specMode == MeasureSpec.EXACTLY) {// We were told how big to be, so nothing to do.result = specSize;} else {// The lines should already be broken up. Calculate our max desired height// for our current mode.int numLines;if (mExpanded) {numLines = mBreakerExpanded.getLines().size();}else {numLines = mBreakerCollapsed.getLines().size();}result = numLines * (int) (-mAscent + mTextPaint.descent())+ getPaddingTop()+ getPaddingBottom();// Respect AT_MOST value if that was what is called for by measureSpec.if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}/*** Render the text* * @see android.view.View#onDraw(android.graphics.Canvas)*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);List<int[]> lines;LineBreaker breaker;if (mExpanded) {breaker = mBreakerExpanded;lines = mBreakerExpanded.getLines();}else {breaker = mBreakerCollapsed;lines = mBreakerCollapsed.getLines();}float x = getPaddingLeft();float y = getPaddingTop() + (-mAscent);for (int i = 0; i < lines.size(); i++) {// Draw the current line.int[] pair = lines.get(i);canvas.drawText(mText, pair[0], pair[1]+1, x, y, mTextPaint);// Draw the ellipsis if necessary.if (i == lines.size() - 1) {if (breaker.getRequiredEllipsis()) {canvas.drawText(mStrEllipsis, x + breaker.getLengthLastEllipsizedLine(), y, mTextPaint);if (mDrawEllipsizeMoreString) {int lastColor = mTextPaint.getColor();mTextPaint.setColor(mColorEllipsizeMore);if (mRightAlignEllipsizeMoreString) {// Seems to not be right...canvas.drawText(mStrEllipsisMore, canvas.getWidth()-(breaker.getLengthEllipsisMore()+getPaddingRight()+getPaddingLeft()), y, mTextPaint);}else {canvas.drawText(mStrEllipsisMore, x + breaker.getLengthLastEllipsizedLinePlusEllipsis(), y, mTextPaint);}mTextPaint.setColor(lastColor);}}}y += (-mAscent + mTextPaint.descent());if (y > canvas.getHeight()) {break;}}}public boolean getIsExpanded() {return mExpanded;}public void expand() {mExpanded = true;requestLayout();invalidate();}public void collapse() {mExpanded = false;requestLayout();invalidate();}private int breakWidth(int availableWidth) {int widthUsed = 0;if (mExpanded) {widthUsed =mBreakerExpanded.breakText(mText, availableWidth - getPaddingLeft() - getPaddingRight(), mTextPaint);}else {widthUsed =mBreakerCollapsed.breakText(mText, mStrEllipsis, mStrEllipsisMore, mMaxLines, availableWidth - getPaddingLeft() - getPaddingRight(), mTextPaint);}return widthUsed + getPaddingLeft() + getPaddingRight();}/*** Used internally to break a string into a list of integer pairs. The pairs are* start and end locations for lines given the current available layout width.*/private static class LineBreaker{/** Was the input text long enough to need an ellipsis? */private boolean mRequiredEllipsis;/** Beginning and end indices for the input string. */private ArrayList<int[]> mLines;/** The width in pixels of the last line, used to draw the ellipsis if necessary. */private float mLengthLastLine;/** The width of the ellipsis string, so we know where to draw the ellipsisMore string* if necessary.*/private float mLengthEllipsis;/** The width of the ellipsizeMore string, same use as above. */private float mLengthEllipsisMore;public LineBreaker() {mRequiredEllipsis = false;mLines = new ArrayList<int[]>();}/*** Used for breaking text in 'expanded' mode, which needs no ellipse.* Uses as many lines as is necessary to accomodate the entire input* string.* @param input String to be broken.* @param maxWidth Available layout width.* @param tp Current paint object with styles applied to it.*/public int breakText(String input, int maxWidth, TextPaint tp) {return breakText(input, null, null, -1, maxWidth, tp);}/*** Used for breaking text, honors ellipsizing. The string will be broken into lines using* the available width. The last line will subtract the physical width of the ellipsis* string from maxWidth to reserve room for the ellipsis. If the ellpsisMore string is set,* then space will also be reserved for its length as well.* @param input String to be broken.* @param ellipsis Ellipsis string, like "..."* @param ellipsisMore Optional space reservation after the ellipsis, like " Read More!"* @param maxLines Max number of lines to allow before ellipsizing.* @param maxWidth Available layout width.* @param tp Current paint object with styles applied to it.*/public int breakText(String input, String ellipsis,String ellipsisMore,int maxLines, int maxWidth, TextPaint tp) {mLines.clear();mRequiredEllipsis = false;mLengthLastLine = 0.0f;mLengthEllipsis = 0.0f;mLengthEllipsisMore = 0.0f;// If maxWidth is -1, interpret that as meaning to render the string on a single// line. Skip everything.if (maxWidth == -1) {mLines.add(new int[]{ 0, input.length() });return (int)(tp.measureText(input) + 0.5f);}// Measure the ellipsis string, and the ellipsisMore string if valid.if (ellipsis != null) {mLengthEllipsis = tp.measureText(ellipsis);}if (ellipsisMore != null) {mLengthEllipsisMore = tp.measureText(ellipsisMore);}// Start breaking.int posStartThisLine = -1;float lengthThisLine = 0.0f;boolean breakWords = true;int pos = 0;while (pos < input.length()) {if (posStartThisLine == -1) {posStartThisLine = pos;}if (mLines.size() == maxLines) {mRequiredEllipsis = true;break;}float widthOfChar = tp.measureText(input.charAt(pos) + "");boolean newLineRequired = false;if(!hasChinese(input)){/**english*/// Check for a new line character or if we've run over max width.if (input.charAt(pos) == '\n') {newLineRequired = true;// We want the current line to go up to the character right before the// new line char, and we want the next line to start at the char after// this new line char.mLines.add(new int[] { posStartThisLine, pos-1 });}else if (lengthThisLine + widthOfChar >= maxWidth) {newLineRequired = true;// We need to backup if we are in the middle of a word.if (input.charAt(pos) == ' ' || breakWords == false) {// Backup one character, because it doesn't fit on this line.pos--;// So this line includes up to the character before the space.mLines.add(new int[] { posStartThisLine, pos });}else {// Backup until we are at a space.Log.v("*******", "*********************************now char = " + input.charAt(pos));while (input.charAt(pos) != ' ') {pos--;}// This line includes up to the space.mLines.add(new int[] { posStartThisLine, pos });}}}else{/**chinese*/// Check for a new line character or if we've run over max width.if (input.charAt(pos) == '\n') {newLineRequired = true;// We want the current line to go up to the character right before the// new line char, and we want the next line to start at the char after// this new line char.mLines.add(new int[] { posStartThisLine, pos-1 });}else if (lengthThisLine + widthOfChar >= maxWidth) {newLineRequired = true;// This line includes up to the space.mLines.add(new int[] { posStartThisLine, pos });}}if (newLineRequired) {// The next cycle should reset the position if it sees it's -1 (to whatever i is).posStartThisLine = -1;// Reset line length for next iteration.lengthThisLine = 0.0f;// When we get to the last line, subtract the width of the ellipsis.if (mLines.size() == maxLines - 1) {maxWidth -= (mLengthEllipsis + mLengthEllipsisMore);// We also don't need to break on a full word, it'll look a little// cleaner if all breaks on the final lines break in the middle of// the last word.breakWords = false;}}else {if(!hasChinese(input)){/**english*/lengthThisLine += widthOfChar;}else{/**chinese*/lengthThisLine += (widthOfChar + 0.5f);}// If we're on the last character of the input string, add on whatever we have leftover.if (pos == input.length() - 1) {mLines.add(new int[] { posStartThisLine, pos });}}pos++;}// If we ellipsized, then add the ellipsis string to the end.if (mRequiredEllipsis) {int[] pairLast = mLines.get(mLines.size()-1);mLengthLastLine = tp.measureText(input.substring(pairLast[0], pairLast[1] + 1));}// If we required only one line, return its length, otherwise we used// whatever the maxWidth supplied was.if (mLines.size() == 0) {return 0;}else if (mLines.size() == 1) {return (int)(tp.measureText(input) + 0.5f);}else {return maxWidth;}}public boolean getRequiredEllipsis() {return mRequiredEllipsis;}public List<int[]> getLines() {return mLines;}public float getLengthLastEllipsizedLine() {return mLengthLastLine;}public float getLengthLastEllipsizedLinePlusEllipsis() {return mLengthLastLine + mLengthEllipsis;}public float getLengthEllipsis() {return mLengthEllipsis;}public float getLengthEllipsisMore() {return mLengthEllipsisMore;}/*** ÅжÏÎı¾ÖÐÊÇ·ñº¬ÓÐÖÐÎÄ*/private boolean hasChinese(String input){return input.getBytes().length != input.length();}}}
package com.test;import android.app.Activity;
import android.os.Bundle;
import android.view.ViewGroup.LayoutParams;
import android.widget.LinearLayout;public class MyClipActivity extends Activity {@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);LinearLayout llContent = (LinearLayout) findViewById(R.id.llvg);MyClipTextView tv2 = new MyClipTextView(this);tv2.setLayoutParams(new LayoutParams(100, 100));tv2.setLayoutParams(new LayoutParams(LayoutParams.FILL_PARENT, LayoutParams.WRAP_CONTENT));tv2.setEllipsis("...");tv2.setEllipsisMore("");tv2.setMaxLines(5);tv2.setText(getResources().getString(R.string.testcn1));tv2.setPadding(10, 10, 10, 10);tv2.setBackgroundColor(0xFFFCDFB2);llContent.addView(tv2);}}
package ru.gzt.newsreader.widgets;import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Paint.Align;
import android.text.TextPaint;
import android.util.Log;
import android.view.View;import java.util.ArrayList;
import java.util.List;public class TextViewMultilineEllipse extends View {private TextPaint mTextPaint;private String mText;private int mAscent;private String mStrEllipsis;private String mStrEllipsisMore;private int mMaxLines;private boolean mDrawEllipsizeMoreString;private int mColorEllipsizeMore;private boolean mRightAlignEllipsizeMoreString;private boolean mExpanded;private LineBreaker mBreakerExpanded;private LineBreaker mBreakerCollapsed;public TextViewMultilineEllipse(Context context) {super(context);// TODO Auto-generated constructor stubmExpanded = false;mDrawEllipsizeMoreString = true;mRightAlignEllipsizeMoreString = false;mMaxLines = -1;mStrEllipsis = "...";mStrEllipsisMore = "";mColorEllipsizeMore = 0xFF0000FF;mBreakerExpanded = new LineBreaker();mBreakerCollapsed = new LineBreaker();// Default font size and color.mTextPaint = new TextPaint();mTextPaint.setAntiAlias(true);mTextPaint.setTextSize(13);mTextPaint.setColor(0xFF000000);mTextPaint.setTextAlign(Align.LEFT);}/*** Sets the text to display in this widget.* * @param text* The text to display.*/public void setText(String text) {mText = text;requestLayout();invalidate();}/*** Sets the text size for this widget.* * @param size* Font size.*/public void setTextSize(int size) {mTextPaint.setTextSize(size);requestLayout();invalidate();}/*** Sets the text color for this widget.* * @param color* ARGB value for the text.*/public void setTextColor(int color) {mTextPaint.setColor(color);invalidate();}/*** The string to append when ellipsizing. Must be shorter than the available* width for a single line!* * @param ellipsis* The ellipsis string to use, like "...", or "-----".*/public void setEllipsis(String ellipsis) {mStrEllipsis = ellipsis;}/*** Optional extra ellipsize string. This* * @param ellipsisMore*/public void setEllipsisMore(String ellipsisMore) {mStrEllipsisMore = ellipsisMore;}/*** The maximum number of lines to allow, height-wise.* * @param maxLines*/public void setMaxLines(int maxLines) {mMaxLines = maxLines;}/*** Turn drawing of the optional ellipsizeMore string on or off.* * @param drawEllipsizeMoreString* Yes or no.*/public void setDrawEllipsizeMoreString(boolean drawEllipsizeMoreString) {mDrawEllipsizeMoreString = drawEllipsizeMoreString;}/*** Font color to use for the optional ellipsizeMore string.* * @param color* ARGB color.*/public void setColorEllpsizeMore(int color) {mColorEllipsizeMore = color;}/*** When drawing the ellipsizeMore string, either draw it wherever ellipsizing* on the last line occurs, or always right align it. On by default.* * @param rightAlignEllipsizeMoreString* Yes or no.*/public void setRightAlignEllipsizeMoreString(boolean rightAlignEllipsizeMoreString) {mRightAlignEllipsizeMoreString = rightAlignEllipsizeMoreString;}/*** @see android.view.View#measure(int, int)*/@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {setMeasuredDimension(measureWidth(widthMeasureSpec), measureHeight(heightMeasureSpec));}/*** Determines the width of this view* * @param measureSpec* A measureSpec packed into an int* @return The width of the view, honoring constraints from measureSpec*/private int measureWidth(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);if (specMode == MeasureSpec.EXACTLY) {// We were told how big to be.result = specSize;// Format the text using this exact width, and the current mode.breakWidth(specSize);} else {if (specMode == MeasureSpec.AT_MOST) {// Use the AT_MOST size - if we had very short text, we may need even// less// than the AT_MOST value, so return the minimum.result = breakWidth(specSize);result = Math.min(result, specSize);} else {// We're not given any width - so in this case we assume we have an// unlimited// width?breakWidth(specSize);}}return result;}/*** Determines the height of this view* * @param measureSpec* A measureSpec packed into an int* @return The height of the view, honoring constraints from measureSpec*/private int measureHeight(int measureSpec) {int result = 0;int specMode = MeasureSpec.getMode(measureSpec);int specSize = MeasureSpec.getSize(measureSpec);mAscent = (int) mTextPaint.ascent();if (specMode == MeasureSpec.EXACTLY) {// We were told how big to be, so nothing to do.result = specSize;} else {// The lines should already be broken up. Calculate our max desired height// for our current mode.int numLines;if (mExpanded) {numLines = mBreakerExpanded.getLines().size();} else {numLines = mBreakerCollapsed.getLines().size();}result = numLines * (int) (-mAscent + mTextPaint.descent()) + getPaddingTop() + getPaddingBottom();// Respect AT_MOST value if that was what is called for by measureSpec.if (specMode == MeasureSpec.AT_MOST) {result = Math.min(result, specSize);}}return result;}/*** Render the text* * @see android.view.View#onDraw(android.graphics.Canvas)*/@Overrideprotected void onDraw(Canvas canvas) {super.onDraw(canvas);List<int[]> lines;LineBreaker breaker;if (mExpanded) {breaker = mBreakerExpanded;lines = mBreakerExpanded.getLines();} else {breaker = mBreakerCollapsed;lines = mBreakerCollapsed.getLines();}float x = getPaddingLeft();float y = getPaddingTop() + (-mAscent);for (int i = 0; i < lines.size(); i++) {// Draw the current line.int[] pair = lines.get(i);canvas.drawText(mText, pair[0], pair[1] + 1, x, y, mTextPaint);// Draw the ellipsis if necessary.if (i == lines.size() - 1) {if (breaker.getRequiredEllipsis()) {canvas.drawText(mStrEllipsis, x + breaker.getLengthLastEllipsizedLine(), y, mTextPaint);if (mDrawEllipsizeMoreString) {int lastColor = mTextPaint.getColor();mTextPaint.setColor(mColorEllipsizeMore);if (mRightAlignEllipsizeMoreString) {// Seems to not be right...canvas.drawText(mStrEllipsisMore, canvas.getWidth() - (breaker.getLengthEllipsisMore() + getPaddingRight() + getPaddingLeft()), y, mTextPaint);} else {canvas.drawText(mStrEllipsisMore, x + breaker.getLengthLastEllipsizedLinePlusEllipsis(), y, mTextPaint);}mTextPaint.setColor(lastColor);}}}y += (-mAscent + mTextPaint.descent());if (y > canvas.getHeight()) {break;}}}public boolean getIsExpanded() {return mExpanded;}public void expand() {mExpanded = true;requestLayout();invalidate();}public void collapse() {mExpanded = false;requestLayout();invalidate();}private int breakWidth(int availableWidth) {int widthUsed = 0;if (mExpanded) {widthUsed = mBreakerExpanded.breakText(mText, availableWidth - getPaddingLeft() - getPaddingRight(), mTextPaint);} else {widthUsed = mBreakerCollapsed.breakTextFast(mText, mStrEllipsis, mStrEllipsisMore, mMaxLines, availableWidth - getPaddingLeft() - getPaddingRight(),mTextPaint);}return widthUsed + getPaddingLeft() + getPaddingRight();}/*** Used internally to break a string into a list of integer pairs. The pairs* are start and end locations for lines given the current available layout* width.*/private static class LineBreaker {/** Was the input text long enough to need an ellipsis? */private boolean mRequiredEllipsis;/** Beginning and end indices for the input string. */private ArrayList<int[]> mLines;/*** The width in pixels of the last line, used to draw the ellipsis if* necessary.*/private float mLengthLastLine;/*** The width of the ellipsis string, so we know where to draw the* ellipsisMore string if necessary.*/private float mLengthEllipsis;/** The width of the ellipsizeMore string, same use as above. */private float mLengthEllipsisMore;public LineBreaker() {mRequiredEllipsis = false;mLines = new ArrayList<int[]>();}/*** Used for breaking text in 'expanded' mode, which needs no ellipse. Uses* as many lines as is necessary to accomodate the entire input string.* * @param input* String to be broken.* @param maxWidth* Available layout width.* @param tp* Current paint object with styles applied to it.*/public int breakText(String input, int maxWidth, TextPaint tp) {// return breakText(input, null, null, -1, maxWidth, tp);return breakTextFast(input, maxWidth, tp);}public final int breakTextFast(String input, int maxWidth, TextPaint tp) {CharSequence textCharArray = input.subSequence(0, input.length());int inputLength = textCharArray.length();mLines.clear();int offset = 0;while (offset < inputLength) {int numOfChars = tp.breakText(textCharArray, offset, textCharArray.length(), true, maxWidth, null);mLines.add(new int[] { offset, (offset += numOfChars) - 1 });}return maxWidth;}public final int breakTextFast(String input, String ellipsis, String ellipsisMore, int maxLines, int maxWidth, TextPaint tp) {CharSequence textCharArray = input.subSequence(0, input.length());int inputLength = textCharArray.length();mRequiredEllipsis = false;mLengthLastLine = 0.0f;mLengthEllipsis = 0.0f;mLengthEllipsisMore = 0.0f;if (ellipsis != null) {mLengthEllipsis = tp.measureText(ellipsis);}if (ellipsisMore != null) {mLengthEllipsis = tp.measureText(ellipsisMore);}float maxLineWidth = 0;float[] measuredWidth = new float[1];measuredWidth[0] = 0;mLines.clear();int offset = 0, k = 0;while (k++ < maxLines && offset < inputLength) {int numOfChars = tp.breakText(textCharArray, offset, textCharArray.length(), true, maxWidth, measuredWidth);maxLineWidth = maxLineWidth > measuredWidth[0] ? maxLineWidth : measuredWidth[0];mLines.add(new int[] { offset, (offset += numOfChars) - 1 });}int[] location = mLines.get(mLines.size() - 1);if (k >= maxLines && location[1] != inputLength - 1) {mRequiredEllipsis = true;location[1] = location[0] + tp.breakText(textCharArray, location[0], location[1], true, maxWidth - (mLengthEllipsis + mLengthEllipsis), measuredWidth)- 1;maxLineWidth = maxLineWidth > measuredWidth[0] ? maxLineWidth : measuredWidth[0];}mLengthLastLine = measuredWidth[0];return (int) maxLineWidth;}public boolean getRequiredEllipsis() {return mRequiredEllipsis;}public List<int[]> getLines() {return mLines;}public float getLengthLastEllipsizedLine() {return mLengthLastLine;}public float getLengthLastEllipsizedLinePlusEllipsis() {return mLengthLastLine + mLengthEllipsis;}public float getLengthEllipsis() {return mLengthEllipsis;}public float getLengthEllipsisMore() {return mLengthEllipsisMore;}/*** ÅжÏÎı¾ÖÐÊÇ·ñº¬ÓÐÖÐÎÄ*/private boolean hasChinese(String input) {return input.getBytes().length != input.length();}}}
import java.util.ArrayList;
import java.util.List;import android.content.Context;
import android.graphics.Canvas;
import android.text.Layout;
import android.text.Layout.Alignment;
import android.text.StaticLayout;
import android.text.TextUtils.TruncateAt;
import android.util.AttributeSet;
import android.widget.TextView;public class EllipsizingTextView extends TextView {private static final String ELLIPSIS = "...";public interface EllipsizeListener {void ellipsizeStateChanged(boolean ellipsized);}private final List<EllipsizeListener> ellipsizeListeners = new ArrayList<EllipsizeListener>();private boolean isEllipsized;private boolean isStale;private boolean programmaticChange;private String fullText;private int maxLines = -1;private float lineSpacingMultiplier = 1.0f;private float lineAdditionalVerticalPadding = 0.0f;public EllipsizingTextView(Context context) {super(context);}public EllipsizingTextView(Context context, AttributeSet attrs) {super(context, attrs);}public EllipsizingTextView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);}public void addEllipsizeListener(EllipsizeListener listener) {if (listener == null) {throw new NullPointerException();}ellipsizeListeners.add(listener);}public void removeEllipsizeListener(EllipsizeListener listener) {ellipsizeListeners.remove(listener);}public boolean isEllipsized() {return isEllipsized;}@Overridepublic void setMaxLines(int maxLines) {super.setMaxLines(maxLines);this.maxLines = maxLines;isStale = true;}public int getMaxLines() {return maxLines;}@Overridepublic void setLineSpacing(float add, float mult) {this.lineAdditionalVerticalPadding = add;this.lineSpacingMultiplier = mult;super.setLineSpacing(add, mult);}@Overrideprotected void onTextChanged(CharSequence text, int start, int before, int after) {super.onTextChanged(text, start, before, after);if (!programmaticChange) {fullText = text.toString();isStale = true;}}@Overrideprotected void onDraw(Canvas canvas) {if (isStale) {super.setEllipsize(null);resetText();}super.onDraw(canvas);}private void resetText() {int maxLines = getMaxLines();String workingText = fullText;boolean ellipsized = false;if (maxLines != -1) {Layout layout = createWorkingLayout(workingText);if (layout.getLineCount() > maxLines) {workingText = fullText.substring(0, layout.getLineEnd(maxLines - 1)).trim();while (createWorkingLayout(workingText + ELLIPSIS).getLineCount() > maxLines) {int lastSpace = workingText.lastIndexOf(' ');if (lastSpace == -1) {break;}workingText = workingText.substring(0, lastSpace);}workingText = workingText + ELLIPSIS;ellipsized = true;}}if (!workingText.equals(getText())) {programmaticChange = true;try {setText(workingText);} finally {programmaticChange = false;}}isStale = false;if (ellipsized != isEllipsized) {isEllipsized = ellipsized;for (EllipsizeListener listener : ellipsizeListeners) {listener.ellipsizeStateChanged(ellipsized);}}}private Layout createWorkingLayout(String workingText) {return new StaticLayout(workingText, getPaint(), getWidth() - getPaddingLeft() - getPaddingRight(),Alignment.ALIGN_NORMAL, lineSpacingMultiplier, lineAdditionalVerticalPadding, false);}@Overridepublic void setEllipsize(TruncateAt where) {// Ellipsize settings are not respected}
}
这篇关于textview中有很多行,我只让它显示三行,最后显示...,我设置了android:maxLines=3和android:ellipsize=end,但出现的问题是只显示两行就显示“...”的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!