Detect ActionMode nesting

那年仲夏 提交于 2019-12-23 02:53:11

问题


I use some custom ActionModes in my application. When an action mode is closed, I do some housekeeping, like closing related views, updating changes, etc.. I detect the action mode has been closed in OnDestroyActionMode.

My problem is, when inside of some of my ActionModes, the user may trigger another system actionmode (The text copy/paste/select). In that case, onDestroyActionMode is called and I erroneously asume the user is done with the first actionmode, rather than implement a "stack" functionality, so can I ignore this onDestroyActionMode, let the user edit / cut / etc the text, then reopen the former actionmode when done.

How can I achieve this?


回答1:


Shedding further light on your situation: prior to honeycomb, longPress on a TextView will yield a popup window with options (like 'Select word', 'Select all', and 'Add "someword" to dictionary') while NOT affecting any existing ActionMode both when shown and when dismissed (by pressing back). So this isn't really a problem pre-honeycomb.

More light regarding HTC Sense: Sense does NOT honour TextView.setCustomSelectionActionModeCallback() because Sense doesn't use an ActionMode for the Text selection feature (and clearly don't care if the rest of the world do!). So this problem has a different smell in that situation (I haven't tested the following solution under Sense, so not sure how it'll behave).

A solution is to create your own custom ActionMode.Callback to replace the OS's one and apply it in setCustomSelectionActionModeCallback() of any TextView and/or EditText you desire (though only if device is running honeycomb or greater). Pass a custom onTextSelectionCABDestroyed callback interface to your custom ActionMode.Callback, call it in the onDestroyActionMode method.

Firstly create an interface and implement it where you want to handle the recreation of your original ActionMode (alternatively you may want to use a bus event with something like Otto):

public interface YourCallbackInterface {
    public void onTextSelectionCABDestroyed();
}

and create a new class:

public final class CustomTextSelectionActionModeCallback implements ActionMode.Callback {
WeakReference<YourCallbackinterface> mYourCallbackinterface;
public CustomTextSelectionActionModeCallback(YourCallbackinterface yourCallbackInterface) {
    mYourCallbackinterface = new WeakReference<YourCallbackinterface>(yourCallbackInterface);
}
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
    return false;
}
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
    return true;    //returning true will create the ActionMode
}
@Override
public void onDestroyActionMode(ActionMode mode) {
    //this is the magic where we actually capture the destroy event for TextSelectionCAB and can subsequently do things like recreate the ActionMore that TextSelectionCAB greedily destroyed!
    mYourCallbackinterface.get().onTextSelectionCABDestroyed();
}
@Override
public boolean onPrepareActionMode(ActionMode mode, Menu menu) {
    return false;
}

}

And remember to avoid StackOverflowException when recreating an ActionMode from the onDestroyActionMode of an ActionMode, postDelayed a Runnable to a Handler like this I explain here: Reopen ActionMode (or CAB) after onDestroyActionMode is called

Lastly, if you're using ActionBarSherlock, make sure that your CustomTextSelectionActionModeCallback implements android.view.ActionMode.Callback rather than com.actionbarsherlock.view.ActionMode.Callback.

Note: I haven't played with ActionBarCompat so not sure how all this applies there. If someone knows, please post as comment!



来源:https://stackoverflow.com/questions/16567783/detect-actionmode-nesting

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!