EllipsizeEndTextview末尾省略自定义View

需求:在某些场景下,直接在xml或者代码里面设置android:ellipsize="end"不生效,可以参考这种解决方案,但是会存在截断单词的场景

原理:默认开启自动截取功能autoTruncate = true,可以在xml中设置关闭,需要设置两次super.setText(text, type)文本,第一次设置,是为了拿到的TextView的最大宽度,当文本宽度,大于view的最大宽度,才开始计算截取点,当大于时通过paint.breakText计算截取点,但是计算出的截取点和'...'拼接之后会出现最后一个点显示半个情形,大概原因是因为计算误差导致的,所以在计算的时候多减了一个.的位置距离,后续补充空格处理

使用:同TextView的使用方式一样

自定义View具体实现:

kotlin 复制代码
import android.content.Context
import android.util.AttributeSet
import android.view.ViewGroup
import androidx.appcompat.widget.AppCompatTextView


/**
 * 需要设置两次text才能拿到具体的宽度值
 * 相较之前版本算法上有提升
 * 考虑到代码入侵性,添加了属性做改造
 * autoTruncate = false关闭截取功能,当作一个普通的TextView使用
 */
class EllipsizeEndTextview(context: Context, attributeSet: AttributeSet?) :
    AppCompatTextView(context, attributeSet) {

    //是否自动截取
    private var autoTruncate = true

    //内部缓存一个原始值,方便外部获取
    private var originalText: CharSequence? = ""

    init {
        val a = context.obtainStyledAttributes(attributeSet, R.styleable.EllipsizeEndTextView)
        autoTruncate = a.getBoolean(R.styleable.EllipsizeEndTextView_autoTruncate, true)
        a.recycle()
    }

    override fun setText(text: CharSequence?, type: BufferType?) {
        if (autoTruncate) {
            adaptText(text ?: "", type)
        } else {
            super.setText(text, type)
        }
    }

    private fun adaptText(content: CharSequence, type: BufferType?) {
        if (originalText?.equals(content) == true) return
        originalText = content
        super.setText(text, type)
        post {
            try {
                var availableWidth = width - compoundPaddingStart - compoundPaddingEnd
                if (layoutParams is ViewGroup.MarginLayoutParams) {
                    //某些场景下使用的是外边距,也会影响内部...的显示
                    availableWidth =
                        availableWidth - (layoutParams as ViewGroup.MarginLayoutParams).leftMargin - (layoutParams as ViewGroup.MarginLayoutParams).rightMargin
                }
                val textString = (originalText ?: "").toString()
                if (paint.measureText(textString) <= availableWidth) {
                    return@post
                }
                val ellipsis = "..."
                val ellipsisWidth = paint.measureText(ellipsis)
                //存在计算误差,会导致出现半个点的情况,就多留一个.号的位置,后续用空格补充(和之前count - 1的原理差不多,都是保障.显示完整)
                val maxTextWidth = (availableWidth - ellipsisWidth / 3 * 4).coerceAtLeast(0f)
                val count = paint.breakText(
                    textString.toCharArray(),
                    0,
                    textString.length,
                    maxTextWidth,
                    null
                )
                val display = if (count > 0) {
                    //存在计算误差,添加空格补充,空格数量不定,保障撑满即可
                    textString.substring(0, count) + ellipsis + "      "
                } else {
                    if (ellipsisWidth <= availableWidth) ellipsis else ""
                }
                Log.d("EllipsizeEndTextview", "adaptText: $display")
                super.setText(display, type)
            } catch (e: Exception) {
                Log.e("EllipsizeEndTextview", "adaptText: ${e.message}")
            }
        }
    }

    override fun getText(): CharSequence {
        return originalText ?: ""
    }
}

涉及到的属性:

kotlin 复制代码
<!-- EllipsizeEndTextView 自定义属性 -->
<declare-styleable name="EllipsizeEndTextView">
    <!-- 是否自动截取 -->
    <attr name="autoTruncate" format="boolean" />
</declare-styleable>
相关推荐
云飞云共享云桌面43 分钟前
传统工作站 vs 云飞云共享云桌面:制造业设计云桌面选型深度对比
运维·服务器·前端·网络·3d·架构·制造
huangdong_1 小时前
电商平台图片URL原图转换技术深度解析:从缩略图到高清原图的完整方案
java·后端·spring
UXbot1 小时前
如何选择适合公司项目的UI设计工具?企业选型指南
前端·低代码·ui·团队开发·原型模式·设计规范·web app
記億揺晃着的那天1 小时前
Java 调用外部 Go 程序的实践:ProcessBuilder 在生产环境中的应用
java·golang·processbuilder
JAVA面经实录9171 小时前
Java 数据结构与算法 (终极完整学习文档)
java·数据结构·算法
llz_1121 小时前
web-第四次课后作业
前端·spring boot·web
JAVA面经实录9172 小时前
操作系统面试题
java·服务器·数据库·计算机网络·面试
武清伯MVP2 小时前
前端跨域方案大合集
前端·javascript
一杯奶茶¥3 小时前
基于springboot的失物招领管理系统带万字文档 校园失物招领管理系统 失物认领管理系统java springboot vue
java·vue.js·spring boot·java项目
不能只会打代码3 小时前
边缘视频分析平台的架构设计与性能优化——从750ms到190ms的调优之路
java·spring boot·redis·性能优化·边缘计算·物联网竞赛