仿微信朋友圈TextView點擊查看更多

在這裏插入圖片描述
效果圖如上。需求是文本設置最大顯示的行數,未超過最大行數時,有多少內容顯示多少內容,超過最大行數時只顯示最大行數,並在最後一行末尾添加自定義文本如…展開…點擊查看更多等。
實現思路

  1. 繼承TextView,拿原始要顯示的行數和設置的最大行數最對比。
  2. 運用TextPaint計算出自定義文本的長度。
  3. 運用Layout和TextUtils得出最後一行要顯示的文本和前面行的文本。
  4. 最後拼接成SpannableStringBuilder設置到TextView。

代碼如下

package com.hai.test.widget;
import android.content.Context;
import android.text.Layout;
import android.text.Spannable;
import android.text.SpannableStringBuilder;
import android.text.TextUtils;
import android.text.style.ForegroundColorSpan;
import android.util.AttributeSet;
import androidx.appcompat.widget.AppCompatTextView;
import com.hai.test.R;

/**
 * 點擊查看更多TextView  借鑑https://www.jianshu.com/p/f4f99eb932d4做了優化
 * Created by huanghp on 2019/12/9.
 * Email [email protected]
 */
public class TailTextView extends AppCompatTextView {
    private boolean showTail = true;
    private boolean isEllipsed = false;
    private static final String LINE_BREAKER = "\n";
    private String tailText = "…查看全文";

    public TailTextView(Context context) {
        this(context, null);
    }

    public TailTextView(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public TailTextView(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        //不顯示小尾巴或者已經處理過的不再處理
        if (!showTail || isEllipsed) {
            return;
        }
        int lineCount = getLineCount();
        Layout layout = getLayout();
        int maxLines = getMaxLines();
        //行數沒有到maxLines不處理
        if (maxLines == 0 || lineCount < maxLines || TextUtils.isEmpty(getText())) ;
        else {
            int lineEndIndex = layout.getLineEnd(maxLines - 1);//第maxLines行的首字符offset
            int lineStartIndex = layout.getLineStart(maxLines - 1);//第(maxLines - 1)行的首字符offset
            if (lineEndIndex >= getText().length()) return;

            CharSequence mustShowText = getText().subSequence(0, lineStartIndex);
            float tailWidth = getPaint().measureText(tailText);
            CharSequence lastLineText;
            //最後一個字是個換行符就把這個換行符去掉,不然不能在那一行後面增加文字了
            if (LINE_BREAKER.equals(String.valueOf(getText().charAt(lineEndIndex - 1)))) {
                lastLineText = getText().subSequence(lineStartIndex, lineEndIndex - 1);
            } else {
                lastLineText = getText().subSequence(lineStartIndex, lineEndIndex);
            }
            int availableWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
            CharSequence ellipsizeLastLineText = TextUtils.ellipsize(lastLineText, getPaint(), availableWidth - tailWidth,
                    TextUtils.TruncateAt.END);
            if (ellipsizeLastLineText.length() > 2 && ellipsizeLastLineText != lastLineText) {
                lastLineText = ellipsizeLastLineText.subSequence(0, ellipsizeLastLineText.length() - 1);
            }
            SpannableStringBuilder ssb = new SpannableStringBuilder(mustShowText);
            ssb.append(lastLineText).append(tailText);
            ssb.setSpan(new ForegroundColorSpan(getResources().getColor(R.color.colorAccent)), ssb.length() - tailText.length(), ssb.length(),
                    Spannable.SPAN_INCLUSIVE_INCLUSIVE);
            setText(ssb);
            //重置一下這個位
            isEllipsed = false;
        }
    }
}

重要的地方都有註釋,相信大家一看就明白。
說明一下,大家拿到他還可以進行擴展,比如通過自定義屬性設置自定義文本、設置自定義文本的顏色以及自定義文本的點擊事件,讓用起來更方便。

發佈了77 篇原創文章 · 獲贊 57 · 訪問量 27萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章