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

如何在Android的TextView中实现文本高亮及自定义文本选择弹窗

Android TextView实现选中文本高亮+自定义操作弹窗方案

实现效果参考

效果参考图

第一步:基础配置(XML)

你之前配置的基础属性保留,额外加选中高亮颜色配置:

<TextView
    android:id="@+id/contentTv"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:enabled="true"
    android:textIsSelectable="true"
    android:focusable="true"
    android:longClickable="true"
    <!-- 自定义选中文本的高亮背景色 -->
    android:textColorHighlight="#FFFF00"
    <!-- 可选:自定义选中文本的左右手柄图标 -->
    android:textSelectHandleLeft="@drawable/ic_select_handle"
    android:textSelectHandleRight="@drawable/ic_select_handle"
    android:textSelectHandle="@drawable/ic_select_handle"/>

第二步:替换系统默认操作弹窗,实现自定义菜单

系统默认的选中文本弹窗是通过ActionMode实现的,我们只需要给TextView设置自定义的ActionMode.Callback,重写菜单创建和点击逻辑即可:

Kotlin 示例代码

contentTv.customSelectionActionModeCallback = object : ActionMode.Callback {
    override fun onCreateActionMode(mode: ActionMode?, menu: Menu?): Boolean {
        // 移除系统默认的菜单
        menu?.clear()
        // 添加自定义菜单选项,顺序和文字按需调整
        menu?.add(0, 1, 0, "高亮")
        menu?.add(0, 2, 1, "复制")
        menu?.add(0, 3, 2, "分享")
        menu?.add(0, 4, 3, "备注")
        return true
    }

    override fun onPrepareActionMode(mode: ActionMode?, menu: Menu?): Boolean {
        // 禁用系统默认的选中处理,返回false表示不需要系统处理
        return false
    }

    override fun onActionItemClicked(mode: ActionMode?, item: MenuItem?): Boolean {
        // 获取选中的文本内容
        val start = contentTv.selectionStart
        val end = contentTv.selectionEnd
        val selectedText = contentTv.text.substring(start, end)
        when(item?.itemId) {
            1 -> {
                // 点击高亮选项,给选中区间文本设置永久高亮
                val spannable = SpannableString(contentTv.text)
                spannable.setSpan(
                    BackgroundColorSpan(Color.YELLOW),
                    start,
                    end,
                    Spannable.SPAN_EXCLUSIVE_EXCLUSIVE
                )
                contentTv.text = spannable
                // 结束选中模式
                mode?.finish()
                return true
            }
            2 -> {
                // 自定义复制逻辑
                val clipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
                val clip = ClipData.newPlainText("selectedText", selectedText)
                clipboard.setPrimaryClip(clip)
                mode?.finish()
                return true
            }
            3 -> {
                // 自定义分享逻辑
                val shareIntent = Intent(Intent.ACTION_SEND).apply {
                    type = "text/plain"
                    putExtra(Intent.EXTRA_TEXT, selectedText)
                }
                startActivity(Intent.createChooser(shareIntent, "分享文本到"))
                mode?.finish()
                return true
            }
            4 -> {
                // 自定义备注逻辑,弹出自定义弹窗即可
                showCustomNoteDialog(selectedText)
                mode?.finish()
                return true
            }
            else -> return false
        }
    }

    override fun onDestroyActionMode(mode: ActionMode?) {
        // 选中销毁时的额外处理,按需添加
    }
}

注意事项

  • 如果需要取消已有的高亮效果,遍历Spannable中对应的BackgroundColorSpan移除即可
  • 如果你需要弹窗完全自定义,不需要系统样式的ActionMode菜单,可以在onCreateActionMode中返回false,自己监听TextView的选中变化,手动弹出自定义的PopupWindow即可
  • 适配Android 10+的剪切板权限,复制功能不需要额外申请权限,读取剪切板内容需要适配权限要求

内容的提问来源于stack exchange,提问作者Emon Hossain Munna

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 17:54:03