This is my solution. you can download demo on my github. https://github.com/krossford/KrossLib/tree/master/android-project
This screenshot was a demo that maxLines = 4
, I think it works well.
package com.krosshuang.krosslib.lib.view;
import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.widget.TextView;
import java.util.ArrayList;
/*
?????
How to use it?
> 1.?xml??java???????
> 1.use it like other views on xml and java code.
> 2.[??] setMaxLines ?????xml?? "android:maxLines" ??
> 2.[must] call the setMaxLines method to instead of the xml property android:maxLines.
> 3.[??] ???? setMultilineEllipsizeMode() ??,???????
> 3.[option] you can invoke setMultilineEllipsizeMode method, but I have not implement it.
*/
/**
* android???TextView???ellipsize?????
* Created by krosshuang on 2015/12/17.
*/
public class EllipsizeEndTextView extends TextView {
private static final String LOG_TAG = "EllipsizeTextView";
/** ???????? */
//TODO ??????
public static final int MODE_EACH_LINE = 1;
/** ????????? */
public static final int MODE_LAST_LINE = 2;
private static final String ELLIPSIZE = "...";
private ArrayList<String> mTextLines = new ArrayList<String>();
private CharSequence mSrcText = null;
private int mMultilineEllipsizeMode = MODE_LAST_LINE;
private int mMaxLines = 1;
private boolean mNeedIgnoreTextChangeAndSelfInvoke = false;
public EllipsizeEndTextView(Context context) {
super(context);
}
public EllipsizeEndTextView(Context context, AttributeSet attrs) {
super(context, attrs);
}
public EllipsizeEndTextView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
}
@Override
protected void onTextChanged(CharSequence text, int start, int lengthBefore, int lengthAfter) {
if (!mNeedIgnoreTextChangeAndSelfInvoke) {
super.onTextChanged(text, start, lengthBefore, lengthAfter);
mSrcText = text;
}
}
@Override
public void setMaxLines(int maxlines) {
super.setMaxLines(maxlines);
mMaxLines = maxlines;
}
public int getSupportedMaxLines() {
return mMaxLines;
}
@Override
protected void onDraw(Canvas canvas) {
setVisibleText();
super.onDraw(canvas);
mNeedIgnoreTextChangeAndSelfInvoke = false;
}
private void setVisibleText() {
if (mSrcText == null) {
return;
}
//??????width get available width
final int aw = getWidth() - getPaddingLeft() - getPaddingRight();
String srcText = mSrcText.toString();
//???????????????????????????
String[] lines = srcText.split("\n");
//Log.i(LOG_TAG, "?????: " + lines.length + " ? " + Arrays.toString(lines));
int maxLines = getSupportedMaxLines();
//????????????list
mTextLines.clear();
for (int i = 0; i < lines.length; i++) {
mTextLines.add(lines[i]);
}
switch (mMultilineEllipsizeMode) {
case MODE_EACH_LINE:
break;
default:
case MODE_LAST_LINE:
//????
String eachLine = null;
for (int i = 0; i < mTextLines.size() && i < maxLines - 1; i++) {
eachLine = mTextLines.get(i);
if (getPaint().measureText(eachLine, 0, eachLine.length()) > aw) {
//?????????
boolean isOut = true;
int end = eachLine.length() - 1;
while (isOut) {
if (getPaint().measureText(eachLine.substring(0, end), 0, end) > aw) {
end--;
} else {
isOut = false;
}
}
mTextLines.set(i, eachLine.substring(0, end)); //??????????
mTextLines.add(i + 1, eachLine.substring(end, eachLine.length())); //????????,?????,????????????????,???????
}
}
//??????,??????????????
break;
}
//?? maxLines ? ?????,?????????
int resultSize = Math.min(maxLines, mTextLines.size());
//????????
String lastLine = mTextLines.get(resultSize - 1);
//????????????...
//1.??????????,???????,?????????...
//2.????????,?????????,????????????,????...
if (getPaint().measureText(lastLine, 0, lastLine.length()) > aw || resultSize < mTextLines.size()) {
boolean isOut = true;
int end = lastLine.length();
while (isOut) {
if (getPaint().measureText(lastLine.substring(0, end) + ELLIPSIZE, 0, end + 3) > aw) {
end--;
} else {
isOut = false;
}
}
mTextLines.set(resultSize - 1, lastLine.substring(0, end) + ELLIPSIZE);
}
//??????
StringBuilder sb = new StringBuilder();
for (int i = 0; i < resultSize ; i++) {
sb.append(mTextLines.get(i));
if (i != resultSize - 1) {
sb.append('\n');
}
}
//????,set
if (sb.toString().equals(getText())) {
return;
} else {
mNeedIgnoreTextChangeAndSelfInvoke = true;
setText(sb.toString());
}
}
/**
* ??ellipsize mode,?????
* @deprecated
* */
public void setMultilineEllipsizeMode(int mode) {
mMultilineEllipsizeMode = mode;
}
}