Действие, начатое вызовом getActivity().startActionMode(calback);
, автоматически отменяется после нажатия кнопки "Назад". Возможно ли избежать такого поведения? Мне нужно сделать еще одну операцию после нажатия кнопки в какой-либо ситуации во время действия.
Предотвратите отмену действия, нажав кнопку "Назад"
Ответ 1
Это интересная проблема. Когда ActionMode активен, событие задней клавиши потребляется внутренне. Событие не, распространяемое на onBackPressed()
или onKeyUp(int keyCode, KeyEvent event)
обратные вызовы.
К счастью, вы можете использовать dispatchKeyEvent(KeyEvent event)
, который все еще вызывается.
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
if(mActionModeIsActive) {
if (event.getKeyCode() == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_UP) {
// handle your back button code here
return true; // consumes the back key event - ActionMode is not finished
}
}
return super.dispatchKeyEvent(event);
}
Вы можете задаться вопросом, каково будет поведение, если у вас есть подменю в ActionMode, и вы закрываете его с помощью обратного ключа. В этом случае dispatchKeyEvent()
не вызывается, поэтому вы можете безопасно использовать код.
Вышеприведенный код работает также с ActionBarSherlock. Единственная проблема, которую я обнаружил, - это устройство Android 3.1, когда используется собственный ActionMode, в этом случае dispatchKeyEvent()
не вызывается. Используйте ActionBarSherlock ActionMode для его решения.
Ответ 2
Предлагаемые решения не помогли мне. Поэтому я решил создать событие back
вручную. Мне понадобилось это событие в моем фрагменте, поэтому я создал BaseFragment
, что все мои фрагменты будут расширяться.
public abstract class BaseFragment extends Fragment {
private ActionModeState actionModeState = ActionModeState.ITEM_NOT_CLICKED;
protected enum ActionModeState {
ITEM_NOT_CLICKED, ITEM_CLICKED
}
protected void onActionItemClicked() {
actionModeState = ActionModeState.ITEM_CLICKED;
}
protected void onDestroyActionMode() {
if (actionModeState == ActionModeState.ITEM_NOT_CLICKED) {
onActionModeBackPressed();
} else {
// reset state
actionModeState = ActionModeState.ITEM_NOT_CLICKED;
}
}
protected void onActionModeBackPressed() { }
}
Основной фрагмент
public class YourMainFragment extends BaseMapFragment {
@Override
public void onActionModeBackPressed() {
// you code for action mode back button
}
private ActionMode.Callback actionModeCallback = new ActionMode.Callback() {
@Override
public boolean onActionItemClicked(ActionMode mode, MenuItem item) {
YourMainFragment.this.onActionItemClicked();
....
}
@Override
public void onDestroyActionMode(ActionMode mode) {
YourMainFragment.this.onDestroyActionMode();
...
}
};
Ответ 3
Создайте собственное окно Window.Callback и перехватите событие, прежде чем оно будет передано в AppCompatDelegateImplBase.
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
//default delegate
final Window window = getActivity().getWindow();
mWindowCallbackDelegate = new WindowCallbackDelegate(window.getCallback(), this);
window.setCallback(mWindowCallbackDelegate);
return true;
}
В вашем собственном делегате:
@Override
public boolean dispatchKeyEvent(KeyEvent event) {
return myWindowDelegate.dispatchKeyEvent(event) || mOriginalWindowCallback.dispatchKeyEvent(event);
}
Когда вы уничтожаете режим действия, восстанавливайте ссылку на предыдущий делегат
@Override
public void onDestroyActionMode(ActionMode mode) {
Window.Callback originalWindowCallback = mWindowCallbackDelegate.getOriginalWindowCallback();
if (originalWindowCallback != null) {
getActivity().getWindow().setCallback(originalWindowCallback);
}}
У вас есть подпись делегата:
public class WindowCallbackDelegate implements Window.Callback {...}