You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

调用TextView getLineEnd(4)抛出ArrayIndexOutOfBoundsException异常

问题描述

为TextView配置android:maxLines="5"属性,在确认目标控件承载文本长度足够达到5行及以上的场景下,调用getLineEnd(4)方法抛出ArrayIndexOutOfBoundsException异常,相关信息如下:

异常日志

06-12 02:50:42.256 30175 30175 E ErrorPageActivity: java.lang.ArrayIndexOutOfBoundsException: length=27; index=30
06-12 02:50:42.256 30175 30175 E ErrorPageActivity:     at android.text.StaticLayout.getLineStart(StaticLayout.java:1151)
06-12 02:50:42.256 30175 30175 E ErrorPageActivity:     at android.text.Layout.getLineEnd(Layout.java:1409)
06-12 02:50:42.256 30175 30175 E ErrorPageActivity:     at com.imdb.livingroom.firetv.util.TextViewExtensionsKt.visibleText(TextViewExtensions.kt:13)

问题代码

Kotlin扩展函数实现

fun TextView.visibleText(): String {
    val end = layout.getLineEnd(4)
    return layout.text.toString().substring(0,end);
}

布局XML配置

<TextView
        android:id="@+id/user_review_description"
        style="@style/text_body_two"
        android:layout_width="@dimen/review_description_width"
        android:layout_height="wrap_content"
        android:layout_marginTop="@dimen/micro_margin"
        android:ellipsize="end"
        android:maxLines="5"
        android:layout_marginStart="@dimen/medium_margin"
        android:importantForAutofill= "noExcludeDescendants"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/user_nickname"
        />

运行效果

界面示例

根因分析
  • 调用时机错误:方法调用时TextView尚未完成布局测量与绘制流程,内部持有的Layout对象未完成最终行数计算,即使XML配置了maxLines=5,当前Layout实例实际统计的行数小于5,直接传入索引4(行索引从0开始,对应第5行)访问行信息就会触发数组越界。
  • 系统版本兼容问题:部分Android版本下,配置了ellipsize属性的TextView在文本测量阶段会生成临时中间态Layout对象,该对象的行数统计和最终渲染行数不一致,也会触发越界异常。
  • 列表复用场景问题:如果TextView位于RecyclerView等可复用列表控件中,复用时绑定的Layout可能是上一个条目遗留的旧实例,行信息和当前文本不匹配。
修复方案
  1. 扩展函数增加合法性校验,禁止硬编码行索引,调用行信息API前先校验Layout状态和实际行数,修正后代码如下:
    fun TextView.visibleText(): String {
        val currentLayout = layout ?: return text.toString()
        val actualLineCount = currentLayout.lineCount
        val endIndex = if (actualLineCount >= 5) {
            currentLayout.getLineEnd(4)
        } else {
            currentLayout.text.length
        }
        return currentLayout.text.toString().substring(0, endIndex)
    }
    
  2. 调整调用时机,不要在onCreate、onBindViewHolder等布局未完成的生命周期阶段直接调用该方法,等待TextView布局完成后再执行取值逻辑:
    textView.doOnLayout {
        val visibleContent = it.visibleText()
        // 执行后续业务逻辑
    }
    
  3. 列表场景下必须保留行数校验逻辑,不能依赖XML配置的maxLines值直接写死行索引,避免复用导致的旧Layout数据不匹配问题。

内容的提问来源于stack exchange,提问作者Xiaoyu Jiang

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 19:45:58