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
相关产品推荐
相关产品推荐

