嵌套上下文操作栏

时间:2014-04-16 00:40:35

标签: android webview selection contextual-action-bar

我正在自定义WebView中创建自定义上下文操作栏(CAB)。

我的要求是从第一个CAB中选择一个特定选项将打开第二个CAB。这是最终目标:

When the user enters selection mode, this CAB appears. When they tap the highlighter, this second CAB appears.

我已经做到了这一点,但选择不正常。我知道它看起来是正确的,但如果用户点击其他三个图标中的任何一个,结果就是这样:

Tap other icons. Selection hangs around when it isn't wanted.

如果用户在按下四个初始图标中的任何一个后触摸选择,则应用程序因空指针异常而崩溃。

当用户在选择操作后触摸延迟选择时,应用会尝试访问创建带有图标的CAB的ActionMode(让我们称之为firstActionMode)以使其无效/刷新。但是,当创建具有颜色的CAB时,firstActionMode被销毁(调用secondActionMode)导致空指针异常。


为了清除选择,我发现在clearFocus()方法中调用onDestroyActionMode(firstActionMode)可以很好地完成工作。

private class CustomActionModeCallback extends ActionMode.Callback {
    @Override
    public void onDestroyActionMode(ActionMode mode) {
        clearFocus();
    }
}

但是,实施此操作后,secondActionMode创建其CAB时选择不会保留:

Same as before, but... The selection disappears when any icon is clicked.

从这一点选择颜色实际上会产生所需的功能。然而,虽然这“有效”,但(最不幸的是)它不符合我的要求。当显示由secondActionMode创建的CAB时,我需要选择保持可见和功能

<小时/> 以下是我的自定义类(WebView)及其嵌套ActionMode s

的代码
public class CustomWebView extends WebView {

    private ActionMode.Callback mActionModeCallback;

    @Override
    public ActionMode startActionMode(Callback callback) {
        ViewParent parent = getParent();
        if (parent == null) {
            return null;
        }
        if (callback instanceof HighlightActionModeCallback) {
            mActionModeCallback = callback;
        } else {
            mActionModeCallback = new CustomActionModeCallback();
        }       
        return parent.startActionModeForChild(this, mActionModeCallback);
    }

    private class CustomActionModeCallback implements 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.first_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) {
            // This method is called when the handlebars are moved.
            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.copy:
                // Do stuff
                break;
            case R.id.bookmark:
                // Do stuff
                break;

            case R.id.highlight:
                startActionMode(new HighlightActionModeCallback());
                break;

            case R.id.note:
                // Do stuff
                break;
            default:
                return false;
            }

            mode.finish(); // Action picked, so close the CAB
            return true;
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            clearFocus(); // This is commented in the first four screens.
        }
    }

    private class HighlightActionModeCallback implements 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.highlight_colors, 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) {
            // This method is called when the handlebars are moved.
            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) {
            mode.finish(); // Action picked, so close the CAB
            return true;
        }

        // Called when the user exits the action mode
        @Override
        public void onDestroyActionMode(ActionMode mode) {
            // Remove the selection highlight and handles.
            clearFocus();
        }
    }

}

<小时/> 怎么解决这个问题?任何和所有的帮助表示赞赏。

1 个答案:

答案 0 :(得分:0)

我现在已经解决了这个问题;我过度思考了。解决方案不在于ActionMode,而在菜单中。

如果选择了荧光笔,则不会为颜色菜单启动全新的ActionMode,而是更改图标菜单。保存对MenuonCreateActionMode参数的引用,并设置某种标记;我正在使用布尔值。

private class CustomActionModeCallback implements ActionMode.Callback {

    private boolean highlighterClicked = false;
    private Menu mMenu;

    // Called when the action mode is created; startActionMode() was called
    @Override
    public boolean onCreateActionMode(ActionMode mode, Menu menu) {
        mMenu = menu;
        // Inflate a menu resource providing context menu items
        MenuInflater inflater = mode.getMenuInflater();
        inflater.inflate(R.menu.first_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) {
        // This method is called when the handlebars are moved.
        MenuInflater inflater = mode.getMenuInflater();
        if (highlighterClicked) {
            menu.clear(); // Remove the four icons
            inflater.inflate(R.menu.highlight_colors, menu); // Show the colors
            return true; // This time we did stuff, so return true
        }
        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) {

        highlighterClicked = false;
        switch (item.getItemId()) {
        case R.id.copy:
            // Do stuff
            break;
        case R.id.bookmark:
            // Do stuff
            break;

        case R.id.highlight:
            highlighterClicked = true;
            onPrepareActionMode(mode, mMenu);
            return true;

        case R.id.note:
            // Do stuff
            break;
        default:
            // Any of the colors were picked
            return true;
        }

        mode.finish(); // Action picked, so close the CAB
        return true;
    }

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

选择突出显示和手柄保持活动和功能,颜色选项按预期工作。

删除第二个ActionModeCallback类是安全的;它毫无价值。再次,过度思考。 :P