如何在三星、华为设备的TextInputEditText中屏蔽粘贴选项?
解决TextInputEditText在三星/华为设备上屏蔽粘贴选项失效的问题
问题背景
需在TextInputEditText中屏蔽粘贴选项,现有代码在Pixel及多数设备上可正常生效,但在三星、华为设备上无效。已尝试设置长按监听、自定义SelectionActionModeCallback、输入过滤器、阻止双击等方案,均未解决问题,推测这类设备对文本选择弹出的顶部菜单有自定义处理逻辑。
用户原代码:
fun onRestrictCopyAndPaste(inputText: TextInputEditText, textInputLayout: TextInputLayout){ inputText.setOnLongClickListener { true } inputText.customSelectionActionModeCallback = object : ActionMode.Callback { override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { menu?.removeItem(android.R.id.paste) return false } override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { menu?.removeItem(android.R.id.paste) return false } override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return false } override fun onDestroyActionMode(mode: ActionMode?) {} } }
解决方案
方案1:重写TextInputEditText拦截粘贴操作(推荐)
从输入连接底层拦截粘贴行为,适配所有厂商设备:
class NoPasteTextInputEditText @JvmOverloads constructor( context: Context, attrs: AttributeSet? = null, defStyleAttr: Int = R.attr.editTextStyle ) : TextInputEditText(context, attrs, defStyleAttr) { override fun onCreateInputConnection(outAttrs: EditorInfo): InputConnection { val inputConnection = super.onCreateInputConnection(outAttrs) // 禁用系统建议菜单 outAttrs.flags = outAttrs.flags or EditorInfo.FLAG_NO_SUGGESTIONS // 拦截粘贴操作 return object : InputConnectionWrapper(inputConnection, true) { override fun performContextMenuAction(id: Int): Boolean { // 拦截粘贴菜单点击 if (id == android.R.id.paste) { return true } return super.performContextMenuAction(id) } } } // 禁用长按弹出菜单 override fun onLongClick(event: MotionEvent): Boolean { return true } }
用法:在布局文件中使用这个自定义控件替代原生TextInputEditText即可。
方案2:适配厂商自定义菜单
三星、华为可能使用了自定义菜单ID或文本,遍历菜单移除所有包含“粘贴”的项:
fun onRestrictCopyAndPaste(inputText: TextInputEditText) { inputText.setOnLongClickListener { true } inputText.customSelectionActionModeCallback = object : ActionMode.Callback { override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean { menu?.let { val iterator = it.iterator() while (iterator.hasNext()) { val item = iterator.next() item.title?.takeIf { title -> title.contains("粘贴") }?.let { iterator.remove() } } } // 返回true才能让菜单创建并处理 return true } override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean { menu?.let { val iterator = it.iterator() while (iterator.hasNext()) { val item = iterator.next() item.title?.takeIf { title -> title.contains("粘贴") }?.let { iterator.remove() } } } return true } override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean { return false } override fun onDestroyActionMode(mode: ActionMode?) {} } }
说明:原代码返回false导致ActionMode未被正确初始化,菜单无法被修改,改为返回true后再移除目标菜单项。
方案3:禁用文本选择
如果不需要文本选择功能,直接禁用选择逻辑:
inputText.setTextIsSelectable(false) // 或自定义MovementMethod禁止选择 inputText.movementMethod = object : ScrollingMovementMethod() { override fun onTouchEvent(widget: TextView, buffer: Spannable, event: MotionEvent): Boolean { return true } }
注意:此方案会影响文本滚动、选择等操作,需根据业务场景使用。
内容的提问来源于stack exchange,提问作者Josué Alfonso Huerta
相关产品推荐
相关产品推荐

