Android實現一個可摺疊的TextView

前言

下左是UI給的效果圖,最初準備用Manabu-GT/ExpandableTextView去實現,如下第二、三張圖效果尚可,但是跟實際UI略有出入:

  1. 摺疊後的最後一行沒有省略號。
  2. 摺疊箭頭在文本最下面,而不是在最後一行的最右邊。
    爲了解決這個問題,就只能自己動手擼一個。
    在這裏插入圖片描述在這裏插入圖片描述在這裏插入圖片描述

效果圖

話不多說,上效果圖。跟UI設計圖 基本完全一致。

在這裏插入圖片描述在這裏插入圖片描述

實現思路

  1. 首先需要計算文本在TextView完全顯示的最大行數。
  2. 然後需要獲取文本在TextView中第n行的內容,並且可以設置初始顯示行數m。
  3. 看下圖。

在這裏插入圖片描述

核心代碼

計算行數

/**
     * 計算行數
     */
    private fun initLines() {
        //將文本內容全部給tvFirst,方便後面計算行數,獲取每行的文本內容
        tvFirst.text = text
        tvFirst.post {
            //繪製時獲取tvFirst實際總行數,直接獲取返回的是0
            maxLines = tvFirst.lineCount
            //最大行數小於等於要顯示的行數
            if (maxLines <= showLines) {
                //tvSecond隱藏,只顯示tvFirst
                tvSecond.visibility = View.GONE
                tvFirst.setLines(tvFirst.lineCount)
            } else {
                tvSecond.visibility = View.VISIBLE
                //獲取tvFirst顯示佈局,可根據改佈局獲取文本中每行的開始位置和結束位置
                val layout = tvFirst.layout
                if (isExpand) {//展開
                    //獲取展開最後一行的內容,展開時給tvSecond顯示
                    lastLineStr = text.substring(layout.getLineStart(maxLines - 1), layout.getLineEnd(maxLines - 1))
                    //設置tvFirst的行數=最大行數-1
                    tvFirst.setLines(maxLines - 1)
                    //設置tvSecond的行數控制其顯示內容,此處設置爲maxLines=2是因爲可能存在:
                    //最後一行的內容剛好完全填滿,而tvSecond由於右邊drawableRight和drawablePadding的存在所以可能顯示不全,只能加多一行顯示。
                    tvSecond.maxLines = 2
                    tvSecond.text = lastLineStr
                } else {
                    //設置tvFirst的行數=摺疊時顯示的行數-1
                    tvFirst.setLines(showLines - 1)
                    val start = layout.getLineStart(showLines - 1)
                    val end = layout.getLineEnd(showLines - 1)
                    secondTextLineStr = text.substring(start, end)
                    //獲取摺疊時最後一行的內容,給tvSecond顯示
                    tvSecond.maxLines = 1
                    tvSecond.text = secondTextLineStr
                }
            }
        }

    }

處理列表展開錯亂的情況

/**
     * 在列表中使用賦值文本請使用此方法
     * 用SparseBooleanArray記錄列表中展開的位置,防止錯亂
     */
    fun setText(string: String, collapsedStatus: SparseBooleanArray, position: Int) {
        mCollapsedStatus = collapsedStatus
        mPosition = position
        val isCollapsed = collapsedStatus[position, false]
        this.setText(string, isCollapsed)
    }

使用

XML

<com.demon.expandablelibrary.ExpandableTextView
        android:id="@+id/expandTextView2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_marginTop="20dp"
        android:padding="30dp"
        app:isExpand="true"
        app:showLines="4"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@id/expandTextView1"
        app:textColor="@color/colorPrimary"
        app:textSize="15sp" />

基本賦值

  expandTextView.setText("新西蘭總理傑辛達阿德恩(Jacinda Ardern)表示,新西蘭的華人社區
  是新西蘭歷史最悠久、規模最大的社區之一。")

在列表中使用

class Adapter(val context: Context) : RecyclerView.Adapter<Adapter.Holder>() {
        private val mCollapsedStatus: SparseBooleanArray = SparseBooleanArray()

        class Holder(itemView: View) : RecyclerView.ViewHolder(itemView) {
            val expandText = itemView.findViewById<ExpandableTextView>(R.id.expandText)
            val tvNo = itemView.findViewById<TextView>(R.id.tvNo)
        }

        override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Holder {
            val view = LayoutInflater.from(parent.context).inflate(R.layout.list, parent, false)
            return Holder(view)
        }

        override fun onBindViewHolder(holder: Holder, position: Int) {
            holder.run {
                tvNo.text = "$position"
                expandText.setText(context.getString(R.string.long_text), mCollapsedStatus, position)
            }
        }

        override fun getItemCount(): Int = 20
    }

自定義屬性

屬性 說明
text 文本內容
textColor 字體顏色
textSize 字體大小
expandDrawable 向下展開時的圖標
collapseDrawable 向上摺疊時的圖標
showLines 摺疊時顯示的文本行數,默認3
isExpand 初始是否展開,默認false

更多

Demo和源碼請看:
GitHub:https://github.com/DeMonLiu623/ExpandableTextView

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