Обнаружение вложенности ActionMode

Я использую некоторые пользовательские режимы действий в своем приложении. Когда режим действия закрывается, я выполняю некоторые действия, такие как закрытие связанных представлений, обновление изменений и т. д. Я обнаруживаю, что режим действия был закрыт в OnDestroyActionMode.

Моя проблема в том, что внутри некоторых моих ActionModes пользователь может запускать другой системный режим действий (текстовое копирование/вставка/выбор). В этом случае вызывается onDestroyActionMode, и я ошибочно предполагаю, что пользователь выполнил первый режим действия, а не реализует функциональность «стека», поэтому могу ли я игнорировать это onDestroyActionMode, позволить пользователю редактировать/вырезать/и т. д. текст, а затем снова открыть прежний режим действия, когда сделано.

Как я могу этого добиться?


person rupps    schedule 15.05.2013    source источник


Ответы (1)


Проливая дополнительный свет на вашу ситуацию: до соты, longPress в TextView выдаст всплывающее окно с параметрами (такими как «Выбрать слово», «Выбрать все» и «Добавить «некоторое слово» в словарь»), НЕ влияя на любой существующий режим ActionMode как при отображении, так и при закрытии (нажатием назад). Так что это на самом деле не проблема до соты.

Подробнее о HTC Sense: Sense НЕ учитывает TextView.setCustomSelectionActionModeCallback(), потому что Sense не использует ActionMode для функции выбора текста (и явно не заботится о том, что это делает остальной мир!). Так что эта проблема имеет другой запах в этой ситуации (я не тестировал следующее решение в Sense, поэтому не уверен, как оно себя поведет).

Решение состоит в том, чтобы создать свой собственный пользовательский ActionMode.Callback, чтобы заменить один из ОС, и применить его в setCustomSelectionActionModeCallback() любого TextView и/или EditText, который вы хотите (но только если устройство работает в сотах или выше). Передайте пользовательский интерфейс обратного вызова onTextSelectionCABDestroyed в свой пользовательский ActionMode.Callback, вызовите его в методе onDestroyActionMode.

Сначала создайте интерфейс и реализуйте его там, где вы хотите воссоздать свой оригинальный ActionMode (в качестве альтернативы вы можете использовать событие шины с чем-то вроде Otto):

public interface YourCallbackInterface {
    public void onTextSelectionCABDestroyed();
}

и создайте новый класс:

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;
}

}

И помните, чтобы избежать StackOverflowException при воссоздании ActionMode из onDestroyActionMode ActionMode, postDelayed Runnable для обработчика, как я объясняю здесь: Повторно открыть ActionMode (или CAB) после вызова onDestroyActionMode

Наконец, если вы используете ActionBarSherlock, убедитесь, что ваш CustomTextSelectionActionModeCallback реализует android.view.ActionMode.Callback, а не com.actionbarsherlock.view.ActionMode.Callback.

Примечание. Я не играл с ActionBarCompat, поэтому не уверен, как все это применимо к ним. Если кто-то знает, пожалуйста, напишите в комментариях!

person straya    schedule 01.10.2013
comment
Спасибо за ваш подробный ответ! В конце концов я решил изменить структуру приложения, чтобы избежать всей ситуации, потому что я не нашел надежного способа решить, был ли onDestroyActionMode вызван взаимодействием с пользователем или системой для открытия другого режима действия. Что-то настолько простое, как это, стало ужасно сложным, потому что мое приложение имеет сложную логику с десятками вложенных режимов действий... Я все равно принимаю ваш ответ, потому что он показывает интересные особенности режима действий. - person rupps; 02.10.2013
comment
Я думаю, что эти проблемы заставили многих избегать предательского каньона боли, которым является ActionMode. Но решения уже есть. - person straya; 02.10.2013