接上一篇在
ActivityStarter侧拦截分享类 Activity 的做法:即便能挡住最终界面,客户仍希望 在 EditText、TextView、WebView 等长按文本时,弹出的浮动菜单里就不要出现「分享」「打开」「网页搜索」,避免用户习惯从菜单侧发起跳转。仅对单个应用设置setCustomSelectionActionModeCallback无法覆盖「所有应用」,因此需要在 Framework 层分两路处理:普通文本控件走Editor,WebView 文本选择浮动条走FloatingToolbar。
为什么应用层方案不够用
网上常见示例是在应用里为 EditText 注册 setCustomSelectionActionModeCallback,自定义 ActionMode 菜单。该方式只能约束 自己写的界面,无法约束系统应用、第三方应用以及 WebView 内核菜单,因此本方案直接改 AOSP 文本编辑与浮动工具栏实现。
一、EditText / TextView:修改 Editor.java
路径: frameworks/base/core/java/android/widget/Editor.java
「分享」项由文本选择的 ActionMode / 上下文菜单 创建,与 TextView.ID_SHARE、MENU_ITEM_ORDER_SHARE 等常量相关。做法有两类(与你们实际补丁一致即可):
1. 注释掉「分享」菜单的 menu.add(一处)
在构建上下文菜单时,原逻辑会向 menu 注册 ID_SHARE。将整块注释掉,并加上说明注释,例如:
1 | // 屏蔽搜索(分享入口) |
(中间保留粘贴、全选、自动填充等你们需要保留的项。)
2. ActionMode 工具栏中的「分享」项(另一处,关键字 MENU_ITEM_ORDER_SHARE)
在根据 canPaste() / canShare() 等向 Menu 添加条目时,将「分享」整段用块注释关闭,避免长按后工具栏仍出现分享:
1 | if (mTextView.canPaste()) { |
注意: 注释掉分享后,若还有「网页搜索」等来自 WebView 内部浮动条 的项,需继续看第二节;纯 TextView 场景一般与 Editor 同步收敛即可。
二、WebView:在 FloatingToolbar.java 中过滤菜单
路径: frameworks/base/core/java/com/android/internal/widget/FloatingToolbar.java
调试可知:WebView 长按选中文本后出现的「打开」「分享」「网页搜索」等,多由 FloatingToolbar 在展示前组装菜单。在 doShow() 展示浮动条之前插入一次过滤,只保留复制、粘贴、全选、剪切等系统字符串标题对应的项,其余一律 setVisible(false)。
1. 在 doShow() 开头调用过滤
1 | private void doShow() { |
2. 新增 removeRedundantMenu 方法(示例)
通过标题与系统字符串资源比对,只保留基础编辑能力,隐藏「打开」「分享」「网页搜索」等扩展项:
1 | private void removeRedundantMenu(Menu menu) { |
说明:
- 若某些 ROM 或 WebView 版本把「打开」等做成了与系统字符串不完全一致的标题,需要再按
item.getItemId()或title关键字补充白名单/黑名单。 - 过滤后若出现空菜单或异常,需在真机上覆盖 Chrome WebView、系统 WebView 与典型业务 H5 页回归。
三、联调与边界
| 层级 | 作用范围 | 典型风险 |
|---|---|---|
Editor |
系统 TextView/EditText 系长按 |
需确认 SearchView、自定义 Editor 是否另有入口 |
FloatingToolbar |
WebView 等使用浮动工具栏的场景 | 不同语言下 title 可能本地化,需抽样验证 |
| 与上一篇配合 | ActivityStarter 兜底 |
即使菜单漏出,仍可拦截最终 Activity |
本文链接:
http://longzhiye.top/2025/12/14/2025-12-14/