系统自带文本省略位置只有开始、中间、末尾,不适用指定省略号后显示几位字符的情况,适配含各种表情符号。
<declare-styleable name="EllipsizeTextView">
<attr name="ellipsize_text" format="string|reference" />
<attr name="ellipsize_index" format="integer|reference" />
</declare-styleable>
public class MyEllipsizeTextView extends AppCompatTextView {
private static final String DEFAULT_ELLIPSIZE_TEXT = "...";
private static final int DEFAULT_ELLIPSIZE_INDEX = 7;
private CharSequence mEllipsizeText;
private CharSequence mOriginText;
private int mMaxLines;
private int mEllipsizeIndex;
public MyEllipsizeTextView(Context context) {
super(context);
}
public MyEllipsizeTextView(Context context, AttributeSet attrs) {
super(context, attrs);
TypedArray ta = context.obtainStyledAttributes(attrs, R.styleable.EllipsizeTextView);
mEllipsizeText = ta.getText(R.styleable.EllipsizeTextView_ellipsize_text);
mEllipsizeIndex = ta.getInt(R.styleable.EllipsizeTextView_ellipsize_index, DEFAULT_ELLIPSIZE_INDEX);
if (mEllipsizeText == null) {
mEllipsizeText = DEFAULT_ELLIPSIZE_TEXT;
}
ta.recycle();
}
public MyEllipsizeTextView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
}
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
super.onMeasure(widthMeasureSpec, heightMeasureSpec);
setText(mOriginText);
}
@Override
public void setMaxLines(int maxLines) {
if (mMaxLines != maxLines) {
super.setMaxLines(maxLines);
mMaxLines = maxLines;
}
}
@Override
public void setText(CharSequence text, BufferType type) {
mOriginText = text;
int maxLineCount = Math.max(1, mMaxLines);
String content = getEllipsizeString((String) text, maxLineCount);
super.setText(content, type);
}
private int getContentWidth() {
Layout layout = getLayout();
if (layout != null) {
return layout.getWidth() - getPaddingLeft() - getPaddingRight();
}
return -1;
}
private String getEllipsizeString(String originText, int maxLines) {
int textLength = originText.length();
TextPaint mPaint = getPaint();
float width = getContentWidth() - mPaint.measureText(originText.substring(0, 1));
float totalWidth = width * maxLines;
MeasuredText text = new Builder(originText.toCharArray()).appendStyleRun(mPaint, textLength, true).build();
if (totalWidth > text.getWidth(0, textLength ) || width < 0) {
return originText;
}
int rightIndex = textLength - mEllipsizeIndex;
do {
if (text.getCharWidthAt(rightIndex) == 0) {
rightIndex--;
}
} while (text.getCharWidthAt(rightIndex) == 0);
float endWidth = mPaint.measureText((String) mEllipsizeText) + text.getWidth(rightIndex,
textLength );
char[] copiedBuffer = new char[textLength ];
TextUtils.getChars(originText, 0, textLength , copiedBuffer, 0);
StringBuilder sb = new StringBuilder();
int lastLeftIndex = 0;
int leftIndex = 0;
float textWidth;
for (int i = 0; i < maxLines; i++) {
if (i == maxLines - 1) {
textWidth= width - endWidth;
} else {
textWidth= width;
}
while (leftIndex < textLength ) {
textWidth-= text.getCharWidthAt(leftIndex);
if (textWidth < 0.0f) {
break;
}
leftIndex++;
}
while (leftIndex > 0 && copiedBuffer[leftIndex - 1] == ' ') {
leftIndex--;
}
sb.append(originText.substring(lastLeftIndex, leftIndex));
lastLeftIndex = leftIndex;
if (i < maxLines - 1) {
sb.append("\n");
}
}
sb.append(mEllipsizeText);
sb.append(originText.substring(rightIndex, textLength));
return sb.toString();
}
}