package com.gh.common.view; import android.content.Context; import android.graphics.Color; import android.os.Build; import android.text.Layout; import android.text.SpannableStringBuilder; import android.text.Spanned; import android.text.TextPaint; import android.text.style.BackgroundColorSpan; import android.text.style.ClickableSpan; import android.util.AttributeSet; import android.view.View; import androidx.appcompat.widget.AppCompatTextView; import androidx.core.content.ContextCompat; import com.gh.common.util.DisplayUtils; import com.gh.gamecenter.R; public class ExpendTextView extends AppCompatTextView { private CharSequence mSnapshotText; private String mExpendText = "...全文"; private int mMaxLines = 3; // 由于sdk版本限制(getMaxLines) 这里设置默认值 private boolean mInitLayout = false; private boolean mOpenLayout = false; private ExpandCallback mExpandCallback; public ExpendTextView(Context context) { super(context); } public ExpendTextView(Context context, AttributeSet attrs) { super(context, attrs); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) { mMaxLines = getMaxLines(); } } @Override protected void onLayout(boolean changed, int left, int top, int right, int bottom) { super.onLayout(changed, left, top, right, bottom); if (mInitLayout && !mOpenLayout && getLineCount() > mMaxLines) { mSnapshotText = getText(); mInitLayout = false; showExpendButton(); } } public void setExpendText(String text) { this.mExpendText = text; } public void setExpandCallback(ExpandCallback callback) { this.mExpandCallback = callback; } @Override public void setText(CharSequence text, BufferType type) { mInitLayout = true; super.setText(text, type); } private void showExpendButton() { Layout layout = getLayout(); int start = layout.getLineStart(0); int lastLineEnd = layout.getLineEnd(mMaxLines - 1); int lastLineStart = layout.getLineStart(mMaxLines - 1); float lastLineRight = layout.getLineRight(mMaxLines - 1); int viewWidth = getWidth() - getPaddingRight() - getPaddingLeft(); TextPaint paint = getPaint(); float expendTextWidth = paint.measureText(mExpendText); CharSequence content = mSnapshotText.subSequence(start, lastLineEnd); if (viewWidth - lastLineRight > expendTextWidth) { content = content.toString().trim() + mExpendText; } else { CharSequence lastText = mSnapshotText.subSequence(lastLineStart, lastLineEnd); for (int i = lastText.length() - 1; i > 0; i--) { CharSequence sequence = lastText.subSequence(0, i); float w = paint.measureText(sequence.toString()); if (viewWidth - w - DisplayUtils.dip2px(5) > expendTextWidth) { content = mSnapshotText.subSequence(start, lastLineStart + i) + mExpendText; break; } } } SpannableStringBuilder msp = new SpannableStringBuilder(mSnapshotText); int length = msp.length(); int startPosition = content.length() - mExpendText.length(); startPosition = startPosition < 0 ? 0 : startPosition; msp.replace(startPosition, length, mExpendText); msp.setSpan(new ClickableSpan() { @Override public void updateDrawState(TextPaint ds) { super.updateDrawState(ds); ds.setColor(ContextCompat.getColor(getContext(), R.color.theme)); ds.setUnderlineText(false); } @Override public void onClick(View widget) { mOpenLayout = true; setMaxLines(Integer.MAX_VALUE); setText(mSnapshotText); if (mExpandCallback != null) { mExpandCallback.onExpand(); } } }, startPosition + 3, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); msp.setSpan(new BackgroundColorSpan(Color.WHITE), startPosition, msp.length(), Spanned.SPAN_EXCLUSIVE_EXCLUSIVE); setText(msp); setMovementMethod(CustomLinkMovementMethod.getInstance()); } public void setExpendMaxLines(int maxLines) { mMaxLines = maxLines; setMaxLines(maxLines); } public interface ExpandCallback { void onExpand(); } }