2

I am trying to implement back navigation through my fragments which are called in specific order: A->B->C and by going back with hardware button I would like them to remain order.

I am using fragmenttransaction.replace in order to switch fragment with no addToBackStack because it made my ActionBarMenu to misbehave.

Problem is that when I am on fragment C back button is going back directly to A. I found out that it is because click event is executed twice I am going to B and directly to 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")
}

logcat result:

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

Can anyone give me a hint how I can avoide twice button events?

Mithrand1r
  • 2,313
  • 9
  • 37
  • 76

5 Answers5

3

I think "click event is executed twice" because you call both event ACTION_DOWN and ACTION_UP. Try this

@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;
    }
PhongVH
  • 51
  • 8
1

You can do two things

  1. "it made my ActionBarMenu to misbehave." FIX this issue.
  2. Override onBackPressed() on your Activity and find find out your current loaded fragment and replace with whichever you want.

    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
    }
    
Bharatesh
  • 8,943
  • 3
  • 38
  • 67
1

2 things:

  1. Even though you're replacing fragments, the old OnKeyListener stays there (and get's fired up later on). Try removing the old OnKeyListener on switching fragments.
  2. Just as S-lightning pointed out, you need to bare in mind that there are two actions associated with a key event (KeyEvent.ACTION_DOWN and KeyEvent.ACTION_UP).
Community
  • 1
  • 1
Bartek Lipinski
  • 30,698
  • 10
  • 94
  • 132
0

Return true if you want to "absorb" the key event and stop it from propagating up to the Activity, which has its own onBackPressed() implementation.

if( keyCode == KeyEvent.KEYCODE_BACK )
{
    goBackToDays();
    return true; // <-- should be TRUE, not FALSE
}
return false;
mwieczorek
  • 2,107
  • 6
  • 31
  • 37
0

Override the onBackPressed() method in hosting activity. do like this.

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

Here is the well explained answer. link

Community
  • 1
  • 1
Ashish M
  • 763
  • 6
  • 13