使用自定义上下文操作栏进行WebView文本选择

 阿都欧巴 发布于 2023-01-18 16:55

我使用了Google和本教程中的指南来制作我自己的上下文操作栏.

private ActionMode.Callback mActionModeCallback = new ActionMode.Callback() {

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.annotation_menu, menu);
        return true;
    }

    // Called each time the action mode is shown.
    // Always called after onCreateActionMode, but
    // may be called multiple times if the mode is invalidated.
    @Override
    public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
        return false; // Return false if nothing is done
    }

    // Called when the user selects a contextual menu item
    @Override
    public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
        switch (item.getItemId()) {
            case R.id.custom_button:
                // do some stuff
                break;
            case R.id.custom_button2:
                // do some other stuff
                break;
            default:
                // This essentially acts as a catch statement
                // If none of the other cases are true, return false
                // because the action was not handled
                return false;
        }
        finish(); // An action was handled, so close the CAB
        return true;
    }

    // Called when the user exits the action mode
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        mActionMode = null;
    }
};

此菜单旨在在用户选择文本时显示,因此它将覆盖本机复制/粘贴菜单.现在我谈到我的问题.

因为我正在覆盖文本选择的功能,所以我还添加了LongClickListener一个WebView并实现了该onLongClick(View v)方法,以便我可以检测用户何时进行选择.

    myWebView.setOnLongClickListener(new View.OnLongClickListener() {

        @Override
        public boolean onLongClick(View v) {
            if (mActionMode != null) {
                return false;
            }

            mActionMode = startActionMode(mActionModeCallback);
            v.setSelected(true);
            return true;
        }
    });

当我长按,我看到我的自定义菜单出现,但没有突出显示文本.
我需要有文本选择功能; 没有它,我的菜单毫无意义.

如何覆盖onLongClick(View v),但保持Android提供的文本选择?
如果无法做到这一点,我是否可以拨打startActionMode(mActionModeCallback)其他地方的电话,以便正常选择文字,但我的自定义菜单也会出现?
如果这些都不可能......帮助.

1 个回答
  • 有一个更容易的方式!请参阅以下更新:D


    为了完整起见,我就是这样解决问题的方法:

    我根据这个答案遵循了这个建议,稍加调整以更接近地匹配被覆盖的代码:

    public class MyWebView extends WebView {
    
        private ActionMode mActionMode;
        private mActionMode.Callback mActionModeCallback;
    
        @Override
        public ActionMode startActionMode(Callback callback) {
            ViewParent parent = getParent();
            if (parent == null) {
                return null;
            }
            mActionModeCallback = new CustomActionModeCallback();
            return parent.startActionModeForChild(this, mActionModeCallback);
        }
    }
    

    从本质上讲,这会强制您的自定义CAB显示而不是Android CAB.现在你必须修改你的回调,以便文本高亮显示将与CAB一起消失:

    public class MyWebView extends WebView {
        ...
        private class CustomActionModeCallback implements ActionMode.Callback {
            ...
            // Everything up to this point is the same as in the question
    
            // Called when the user exits the action mode
            @Override
            public void onDestroyActionMode(ActionMode mode) {
                clearFocus(); // This is the new code to remove the text highlight
                 mActionMode = null;
            }
        }
    }
    

    这里的所有都是它的.请注意,只要您使用MyWebView被覆盖的内容startActionMode,就无法获得本机CAB(复制/粘贴菜单,如果是WebView).有可能实现这种行为,但这不是这段代码的工作方式.


    更新:有一个更简单的方法来做到这一点!上述解决方案效果很好,但这是另一种更简单的方法.

    该解决方案提供的控制较少ActionMode,但它需要的代码远少于上述解决方案.

    public class MyActivity extends Activity {
    
        private ActionMode mActionMode = null;
    
        @Override
        public void onActionModeStarted(ActionMode mode) {
            if (mActionMode == null) {
                mActionMode = mode;
                Menu menu = mode.getMenu();
                // Remove the default menu items (select all, copy, paste, search)
                menu.clear();
    
                // If you want to keep any of the defaults,
                // remove the items you don't want individually:
                // menu.removeItem(android.R.id.[id_of_item_to_remove])
    
                // Inflate your own menu items
                mode.getMenuInflater().inflate(R.menu.my_custom_menu, menu);
            }
    
            super.onActionModeStarted(mode);
        }
    
        // This method is what you should set as your item's onClick
        // <item android:onClick="onContextualMenuItemClicked" />
        public void onContextualMenuItemClicked(MenuItem item) {
            switch (item.getItemId()) {
                case R.id.example_item_1:
                    // do some stuff
                    break;
                case R.id.example_item_2:
                    // do some different stuff
                    break;
                default:
                    // ...
                    break;
            }
    
            // This will likely always be true, but check it anyway, just in case
            if (mActionMode != null) {
                mActionMode.finish();
            }
        }
    
        @Override
        public void onActionModeFinished(ActionMode mode) {
            mActionMode = null;
            super.onActionModeFinished(mode);
        }
    }
    

    这是一个示例菜单,可以帮助您入门:

    <!-- my_custom_menu.xml -->
    <?xml version="1.0" encoding="utf-8"?>
    
    <menu xmlns:android="http://schemas.android.com/apk/res/android">
    
        <item
            android:id="@+id/example_item_1"
            android:icon="@drawable/ic_menu_example_1"
            android:showAsAction="always"
            android:onClick="onContextualMenuItemClicked"
            android:title="@string/example_1">
        </item>
    
        <item
            android:id="@+id/example_item_2"
            android:icon="@drawable/ic_menu_example_2"
            android:showAsAction="ifRoom"
            android:onClick="onContextualMenuItemClicked"
            android:title="@string/example_2">
        </item>
    
    </menu>
    

    而已!你完成了!现在您的自定义菜单将显示,您不必担心选择,您几乎不必关心ActionMode生命周期.

    这几乎完美无缺地WebView占据了整个父母Activity.如果ViewActivity的同时有多个s,我不确定它会有多好用.在这种情况下,可能需要进行一些调整.

    2023-01-18 16:58 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有