Android 从 textView 自定义选择操作模式中删除 CAB 菜单

Android Remove CAB menu from textView Custom Selection Action Mode

我通过这段代码添加了自定义上下文菜单。

ns_text_menu.xml 只包含两项。

this.textViewTest.setCustomSelectionActionModeCallback(new ActionMode.Callback() {
            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {

                menu.clear();

                mode.setTitle("Menu");
                mode.getMenuInflater().inflate(R.menu.ns_text_menu, menu);

                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
                return false;
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

                if (item.getTitle().equals("View Vocab")) {

                    ErrorController.showToast(mContext, "View Vocab : " + textViewTest.getText().toString().substring(textViewTest.getSelectionStart(), textViewTest.getSelectionEnd()));

                }else{//cpy
                    ErrorController.showToast(mContext, "Copy : " + textViewTest.getSelectionStart() + ", " + textViewTest.getSelectionEnd());

                }

                return true;
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {

            }
        });

正如这个答案中提到的(),我使用了代码

menu.clear();

在 onCreateActionMode 上清除默认 CAB 菜单。它清除了一些默认的上下文菜单,但是,这两个菜单仍然存在:

'select all' 和 'dictionary'。

测试机器是galaxy s9+(android 8.0),一个nexus emulator(6.0)。

它们都显示出意想不到的菜单。

我该如何解决这个问题?

好像是在onPrepareActionMode上添加了意想不到的菜单。

要解决此问题,

(1) 将我的自定义菜单的 ID 存储在全局列表中。 (2) 在 onPrepareActionMode 中,移除所有与上面列表中存储的 id 不匹配的菜单。

代码如下所示。

this.textViewTest.setCustomSelectionActionModeCallback(new ActionMode.Callback() {

            private List<Integer> validResIdList = new ArrayList<>();

            @Override
            public boolean onCreateActionMode(ActionMode mode, Menu menu) {


                menu.clear();
                validResIdList.clear();

                mode.getMenuInflater().inflate(R.menu.ns_text_menu, menu);

                for (int i = 0; i < menu.size(); i++) {

                    validResIdList.add(menu.getItem(i).getItemId());
                }

                return true;
            }

            @Override
            public boolean onPrepareActionMode(ActionMode mode, Menu menu) {


                List<Integer> toRemoveResId = new ArrayList<>();

                for (int i = 0; i < menu.size(); i++) {

                    if (menu.getItem(i).getItemId() != (validResIdList.get(0)) && menu.getItem(i).getItemId() != (validResIdList.get(1))) {

                        toRemoveResId.add(menu.getItem(i).getItemId());
                    }
                }

                for (Integer resId : toRemoveResId) {
                    menu.removeItem(resId);
                }

                return true;
            }

            @Override
            public boolean onActionItemClicked(ActionMode mode, MenuItem item) {

                if(validResIdList != null && validResIdList.size() > 0){

                    if (item.getItemId() == validResIdList.get(0)) {

                        ErrorController.showToast(mContext, "View Vocab : " + textViewTest.getText().toString().substring(textViewTest.getSelectionStart(), textViewTest.getSelectionEnd()));
                        mode.finish();

                    } else {//cpy
                        ErrorController.showToast(mContext, "Copy : " + textViewTest.getSelectionStart() + ", " + textViewTest.getSelectionEnd());
                        mode.finish();
                    }
                }

                return true;
            }

            @Override
            public void onDestroyActionMode(ActionMode mode) {

            }
        });

我之所以在 R.id.xxx 上使用 validResIdList 是因为我在一个图书馆项目上实施它。

如果您在应用程序项目中,您可以使用 R.id.xxx 来确定您正在处理的菜单。