2012-07-30 13 views
14

El modo de acción iniciado llamando al getActivity().startActionMode(calback); se cancela automáticamente después de presionar el botón Atrás. Es posible evitar este comportamiento? Necesito hacer otra operación después de presionar el botón Atrás en alguna situación durante el modo de acción.Impedir cancelar el modo de acción presionando el botón Atrás

Respuesta

30

Esto es un problema interesante. Cuando ActionMode está activo, el evento de la tecla de retroceso se consume internamente. El evento es no propagado a onBackPressed() o onKeyUp(int keyCode, KeyEvent event) devoluciones de llamada.

Afortunadamente, puede usar dispatchKeyEvent(KeyEvent event) que todavía se llama.

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

Usted podría preguntarse cuál será el comportamiento en caso de tener un submenú en el ActionMode y lo cierre con la llave. En este caso, no se llama al dispatchKeyEvent() para que pueda usar el código de manera segura.

El código anterior funciona también con ActionBarSherlock. El único problema que encontré es en el dispositivo Android 3.1 cuando se usa el ActionMode nativo, en este caso no se llama al dispatchKeyEvent(). Usa el ActionMode de ActionBarSherlock para resolverlo.

+0

¿Podría estar un poco más claro con lo que quiere decir con "Use ActionMarlock ActionMode para resolverlo"? –

+3

En un dispositivo con Android 3.1, no se llama a 'dispatchKeyEvent()' si no usa ActionBarSherlock. Si lo usa, se llama (ActionBarSherlock usa la implementación personalizada de ActionBar para Android 3.x). – Tomik

+1

Esta respuesta no funciona para mí. ¿Alguna idea sobre mi pregunta aquí? Http: //stackoverflow.com/questions/32683145/prevent-back-button-whilst-actionmode-is-active – Kuffs

0

Las soluciones sugeridas no me funcionaron. Así que decido crear el evento back manualmente. Necesitaba este evento en mi fragmento, así que creé BaseFragment que extenderían todos mis fragmentos.

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() { } 

} 

fragmento principal

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(); 
      ... 
     } 
    }; 
0

Crear su propio evento Window.Callback y la intersección antes de que se pasa a 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; 
    } 

En su propio delegado:

@Override 
public boolean dispatchKeyEvent(KeyEvent event) { 
    return myWindowDelegate.dispatchKeyEvent(event) || mOriginalWindowCallback.dispatchKeyEvent(event); 
} 

Al destruir el modo de acción, restauración referencia al delegado anterior

@Override 
     public void onDestroyActionMode(ActionMode mode) { 
     Window.Callback originalWindowCallback = mWindowCallbackDelegate.getOriginalWindowCallback(); 
     if (originalWindowCallback != null) { 
      getActivity().getWindow().setCallback(originalWindowCallback); 
     }} 

Eres dueño delegado de la firma:

public class WindowCallbackDelegate implements Window.Callback {...}

Cuestiones relacionadas