Estoy tratando de implementar la navegación hacia atrás a través de mis fragmentos que se llaman en un orden específico: A -> B -> C y al volver con el botón de hardware me gustaría que permanecieran en orden .

Estoy usando fragmenttransaction.replace para cambiar el fragmento sin addToBackStack porque hizo que mi ActionBarMenu se portara mal.

El problema es que cuando estoy en el fragmento C el botón de retroceso vuelve directamente a A. Descubrí que es porque el evento click se ejecuta dos veces. Voy a B y directamente a A.

@Override
public void onViewCreated(View view, @Nullable Bundle savedInstanceState) {
    super.onViewCreated(view, savedInstanceState);
    setOnBackButtonPresed();
}

private void setOnBackButtonPresed() {
    getView().setFocusableInTouchMode(true);
    getView().requestFocus();
    getView().setOnKeyListener( new View.OnKeyListener()
    {
        @Override
        public boolean onKey( View v, int keyCode, KeyEvent event )
        {
            if( keyCode == KeyEvent.KEYCODE_BACK )
            {
                goBackToDays();
                return false;
            }
            return false;
        }
    } );
}

private void goBackToDays() {
    Log.e("fragmentC", "executing on back action")
}

Resultado logcat:

03-15 08:37:17.353 21245-21245/com.test E/fragmentC: executing on back action
03-15 08:37:17.390 21245-21245/com.test E/fragmentC: executing on back action

¿Alguien puede darme una pista de cómo puedo evitar eventos de dos botones?

2
Mithrand1r 15 mar. 2017 a las 11:36

5 respuestas

La mejor respuesta

2 cosas:

  1. Aunque eres replacing fragmentos, el antiguo OnKeyListener permanece allí (y se enciende más tarde). Intente eliminar el antiguo OnKeyListener al cambiar fragmentos.
  2. Tal como S-lightning señaló, debe tener en cuenta que hay dos acciones asociadas con un evento clave ({ {X0}} y KeyEvent.ACTION_UP).
1
Community 23 may. 2017 a las 12:00

Creo que "el evento de clic se ejecuta dos veces" porque llamas al evento ACTION_DOWN y ACTION_UP. Prueba esto

@Override
    public boolean onKey( View v, int keyCode, KeyEvent event )
    {
        if( keyCode == KeyEvent.KEYCODE_BACK && event.getAction()== KeyEvent.ACTION_DOWN)
        {
            goBackToDays();
            return false;
        }
        return false;
    }
3
S-lightning 15 mar. 2017 a las 10:20

Anule el método onBackPressed() en la actividad de alojamiento. hazlo así.

private void replaceFragment (Fragment fragment){
  String backStateName = fragment.getClass().getName();

  FragmentManager manager = getSupportFragmentManager();
  boolean fragmentPopped = manager.popBackStackImmediate(backStateName, 0);

  if (!fragmentPopped){ //fragment not in back stack, create it.
     FragmentTransaction ft = manager.beginTransaction();
     ft.replace(R.id.content_frame, fragment);
     ft.addToBackStack(backStateName);
     ft.commit();
  }
}
.

.

@Override
public void onBackPressed(){
  if (getSupportFragmentManager().getBackStackEntryCount() == 1){
    finish();
  }
  else {
    super.onBackPressed();
  }
}

Aquí está la respuesta bien explicada. enlace

0
Community 23 may. 2017 a las 12:25

Devuelva true si desea "absorber" el evento clave y evitar que se propague a la Actividad, que tiene su propia implementación onBackPressed().

if( keyCode == KeyEvent.KEYCODE_BACK )
{
    goBackToDays();
    return true; // <-- should be TRUE, not FALSE
}
return false;
0
mwieczorek 15 mar. 2017 a las 08:44

Puedes hacer dos cosas

  1. "Hizo que mi ActionBarMenu se portara mal". CORREGIR este problema.
  2. Anule onBackPressed() en su Actividad y descubra su fragmento cargado actual y reemplácelo con el que desee.

    Fragment fragment = getSupportFragmentManager().findFragmentById(R.id.your_view_container);
    if (fragment instanceof FragmentThree) {
          //replace with your fragment ie. FragmentTwo
    } else if (fragment instanceof FragmentTwo) {
          //replace with your fragment ie. FragmentOne
    }
    
1
Bharatesh 18 abr. 2018 a las 12:12