Android实现文本折叠效果

小需求:默认展示4行,超过4行出现“查看全部”,点击则加载浮层显示完整内容;

实现是参考下面网址代码,但是有一些改动(主要涉及纯引英文的文本下面网址的代码可能有些问题)

https://www.jianshu.com/p/f4f99eb932d4

 

最终显示代码如下:

import android.content.Context
import android.graphics.Color
import android.support.v7.widget.AppCompatTextView
import android.text.Spannable
import android.text.SpannableStringBuilder
import android.text.TextPaint
import android.text.TextUtils
import android.text.method.LinkMovementMethod
import android.text.style.ClickableSpan
import android.util.AttributeSet
import android.view.View
import android.widget.Toast

/**
 * @date: 2020.02.25
 */
class FoldTextView : AppCompatTextView {

    private var isSupportFold = false
    private var clickCallback: TextClickCallback? = null
    private var isNeedEllipsis = true

    constructor(context: Context) : this(context, null) {
    }

    constructor(context: Context, attrs: AttributeSet?) : this(context, attrs, 0) {}

    constructor(context: Context, attrs: AttributeSet?, defStyleAttr: Int) : super(context, attrs, defStyleAttr) {
        val ta = context.obtainStyledAttributes(attrs, R.styleable.PayFoldTextView)
        isSupportFold = ta.getBoolean(R.styleable.FoldTextView_supportFold, false)
    }


    override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec)

        if (isSupportFold) {
            //获取当前的行数
            val lineCount = lineCount
            val layout = layout
            val maxLines = maxLines

            if (maxLines == 0 || lineCount < maxLines || TextUtils.isEmpty(text)) {
                return
            }

            val totalChars = layout.getLineEnd(maxLines - 1)
            val lastLineStartIndex = layout.getLineStart(maxLines - 1)
            if (totalChars >= text.length) {
                return
            }

            val mustShowText = text.subSequence(0, lastLineStartIndex)
            val tailWidth = paint.measureText(TAIL_TEXT)
            var lastLineText: CharSequence
            if (LINE_BREAKER == text[totalChars - 1].toString()) {
                lastLineText = text.subSequence(lastLineStartIndex, totalChars - 1)
            } else {
                lastLineText = text.subSequence(lastLineStartIndex, totalChars)
            }
            val maxWidth = measuredWidth.toFloat()
            val ellipsizeLastLineText = TextUtils.ellipsize(
                    lastLineText, paint, maxWidth - tailWidth,
                    TextUtils.TruncateAt.END
            )
            if (ellipsizeLastLineText.length > 2 && ellipsizeLastLineText != lastLineText) {
                lastLineText = ellipsizeLastLineText.subSequence(0, ellipsizeLastLineText.length - 1)
                isNeedEllipsis = true
            } else {
                isNeedEllipsis = false
            }

            val spannableStringBuilder = SpannableStringBuilder(mustShowText)
            if (!mustShowText.endsWith("\n")) {
                spannableStringBuilder.append(LINE_BREAKER)
            }
            spannableStringBuilder.append(lastLineText)
            if (isNeedEllipsis) {
                spannableStringBuilder.append("...")
                spannableStringBuilder.append(TAIL_SEPARATOR)
            } else {
                spannableStringBuilder.append(TAIL_SEPARATOR_O)
            }
            spannableStringBuilder.append(buildClickText())
            //重新设置文本
            movementMethod = LinkMovementMethod.getInstance()
            highlightColor = Color.TRANSPARENT //设置点击后的颜色为透明
            super.setText(spannableStringBuilder)
        }

    }

    companion object {

        val LINE_BREAKER = "\n"
        val TAIL_TEXT = "...查看全部"
        val TAIL_SEPARATOR = "    "
        val TAIL_SEPARATOR_O = " "
        val TAIL_TEXT_WITHOUT_ELLIPSIS = "查看全部"
    }

    fun setClickCallback(clickCallback: TextClickCallback?) {
        this.clickCallback = clickCallback
    }

    private fun buildClickText(): SpannableStringBuilder {
        val spannableString =
                SpannableStringBuilder(TAIL_TEXT_WITHOUT_ELLIPSIS)
        val clickableSpan = object : ClickableSpan() {
            override fun onClick(widget: View) {
                clickCallback?.respondClick()
            }

            override fun updateDrawState(ds: TextPaint) {
                super.updateDrawState(ds)
                ds.color = resources.getColor(R.color.pay_color_0086f6)
                ds.isUnderlineText = false
            }
        }
        spannableString.setSpan(clickableSpan, 0, 4, Spannable.SPAN_EXCLUSIVE_EXCLUSIVE)
        return spannableString
    }

    fun setSupportFold(isSupport: Boolean = false) {
        isSupportFold = isSupport
        maxLines = Integer.MAX_VALUE
    }
}

 

<declare-styleable name="FoldTextView">
    <attr name="supportFold" format="boolean"/>
</declare-styleable>

相关注释:

supportFold:是否需要支持文本折叠。

buildClickText()方法主要是给查看全部添加点击事件以及相关样式。

下面代码是:指定Paint属性的宽度下的文本是否与原始文本相同,不相同则需要显示省略号及查看全部。

 

 if (ellipsizeLastLineText.length > 2 && ellipsizeLastLineText != lastLineText) {
                lastLineText = ellipsizeLastLineText.subSequence(0, ellipsizeLastLineText.length - 1)
                isNeedEllipsis = true
            } else {
                isNeedEllipsis = false
            }

 

ellipsize方法需要的相关参数:

text:原始的文本内容 paint:canvas用到的画笔 avail:画布能提供的宽度 where:枚举类型,就是 省略号显示的位置

/**
 * Returns the original text if it fits in the specified width
 * given the properties of the specified Paint,
 * or, if it does not fit, a truncated
 * copy with ellipsis character added at the specified edge or center.
 */
public static CharSequence ellipsize(CharSequence text,
                                     TextPaint p,
                                     float avail, TruncateAt where) {
    return ellipsize(text, p, avail, where, false, null);
}

下面的代码加上"\n"是因为在英文条件下,最后一行的文字可能会显示到倒数第二行,所以强制加上换行符。

  val spannableStringBuilder = SpannableStringBuilder(mustShowText)
            if (!mustShowText.endsWith("\n")) {
                spannableStringBuilder.append(LINE_BREAKER)
            }

 

 

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实现折叠搜索框的搜索功能,你需要在Android中使用SearchView控件,它提供了一个内置的搜索框,可以轻松地添加到你的应用程序中。 以下是实现搜索功能的步骤: 1. 在布局文件中添加SearchView控件: ``` <androidx.appcompat.widget.SearchView android:id="@+id/search_view" android:layout_width="match_parent" android:layout_height="wrap_content" android:iconifiedByDefault="false" app:queryHint="Search" /> ``` 2. 在Activity或Fragment中初始化SearchView并设置OnQueryTextListener监听器: ``` SearchView searchView = findViewById(R.id.search_view); searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { @Override public boolean onQueryTextSubmit(String query) { // 在这里处理搜索提交事件 return false; } @Override public boolean onQueryTextChange(String newText) { // 在这里处理搜索文本变化事件 return false; } }); ``` 3. 在onQueryTextSubmit()方法中,你可以处理用户提交搜索查询的事件,例如,你可以在这里执行搜索操作,或者打开一个新的Activity来显示搜索结果。 4. 在onQueryTextChange()方法中,你可以处理当用户输入搜索文本时的事件,例如,你可以实时更新搜索结果列表。 注意:记得在AndroidManifest.xml文件中添加如下代码来启用搜索功能: ``` <activity android:name=".YourActivity"> <meta-data android:name="android.app.searchable" android:resource="@xml/searchable" /> <intent-filter> <action android:name="android.intent.action.SEARCH" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> ``` 以上就是实现折叠搜索框的搜索功能的步骤,希望能对你有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值