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

Android开发:如何实现TextView的部分文本可编辑?

嘿,针对你开发法语技能测试App时遇到的「TextView部分文本可编辑」需求(类似SoloLearn的效果),我给你几个更靠谱的解决方案,适配你用的Kotlin、Anko技术栈:

解决方案:实现部分文本可编辑的原生方案

方案1:动态组合TextView与EditText(行内嵌入)

这个方案是把静态文本和可编辑字段拆分成多个TextView和EditText,用横向LinearLayout排列,让它们视觉上像连续的一句话。结合Anko的DSL可以快速实现,还能精准控制每个可编辑区域的样式:

Kotlin/Anko代码示例

verticalLayout {
    // 示例句子:"Je ______ français"
    horizontalLayout {
        textView("Je ") {
            textSize = 16f
            textColor = Color.BLACK
        }
        editText {
            hint = "______"
            maxLines = 1
            background = null // 去掉默认输入框背景,只保留下划线
            textSize = 16f
            textColor = Color.BLACK
            // 让输入框宽度匹配内容,避免太宽破坏排版
            layoutParams = LinearLayout.LayoutParams(
                LinearLayout.LayoutParams.WRAP_CONTENT,
                LinearLayout.LayoutParams.WRAP_CONTENT
            )
        }
        textView(" français") {
            textSize = 16f
            textColor = Color.BLACK
        }
    }
}

你可以复用之前的$分割逻辑,把字符串拆成静态段和可编辑段,然后循环生成对应的TextView和EditText,轻松处理多空的测试题。

方案2:单EditText内实现部分区域可编辑

如果希望整个内容在一个输入框里,只允许特定区域编辑,可以用Editable配合Spannable标记不可编辑区域,再用InputFilter限制编辑范围,视觉上完全是连贯的文本:

Kotlin代码示例

val originalText = "Je \$apprends\$ français"
// 先去掉$标记,得到完整文本
val processedText = originalText.replace("\$", "")
val editText = editText {
    text = processedText
    textSize = 16f
}

// 定位可编辑区域的位置(对应原字符串中$包裹的部分)
val startPos = originalText.indexOf("\$") + 1
val endPos = originalText.lastIndexOf("\$")

val editable = editText.text as Editable
// 标记开头到可编辑区域前的部分不可编辑
editable.setSpan(
    object : SpannableStringBuilder.NoCopySpan() {},
    0, startPos - 1,
    Spannable.SPAN_INCLUSIVE_INCLUSIVE
)
// 标记可编辑区域后的部分不可编辑
editable.setSpan(
    object : SpannableStringBuilder.NoCopySpan() {},
    endPos - 1, processedText.length,
    Spannable.SPAN_INCLUSIVE_INCLUSIVE
)

// 设置输入过滤器,只允许编辑目标区域
editText.filters = arrayOf(InputFilter { source, _, _, _, dstart, dend ->
    if (dstart in (startPos-1)..(endPos-2)) source else ""
})

这个方案的交互体验更接近SoloLearn的效果,用户感觉是在一段文本里填空,而不是操作多个输入框。

为什么你之前的方案不够理想?

  • $分割替换EditText:如果句子有多个空或者需要换行,布局会变得零散,对齐和排版很难控制;
  • WebView:性能开销大,而且原生软键盘、输入状态同步的体验远不如原生控件,还会增加包体积。

内容的提问来源于stack exchange,提问作者Ismail ackerboy

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 06:57:19