简体   繁体   中英

Fragment and back button

I have a problem with the back/up button in a Fragment. I have an Activity in which I have some fragments. In one Fragment, that I call "1", I have a list view. When I click on any item it goes to another fragment "2". I need functionality such that the back/up button only works in Fragment 2 but not in Fragment 1.

Is there a way this can be done? I have tried this in the Activity, but I don't understand how can this help:

@Override
public void onBackPressed() {

    int count = getFragmentManager().getBackStackEntryCount();

    if (count == 0) {
        super.onBackPressed();
        //additional code
    } else {
        getFragmentManager().popBackStack();
    }

}

When i change from fragment 1 to fragment 2 i have this code:

  fragment = new MaterialesFragment();
  FragmentManager fragmentManager3 = getFragmentManager();
  fragmentManager3.beginTransaction().replace(R.id.frame, fragment).addToBackStack("tagMateriales").commit();

Thanks a lot :-)

Try to use addToBackStack() method on the FragmentTransaction object you use to replace the fragment2 into the screen:

fragmentManager.beginTransaction().replace(R.id.content_frame,fragment2).addToBackStack("tagHere").commit();

You can pass null as the parameter if you don't need the actual tag.

Please use this code for your 'fragment 2'

public void showFragmentWithoutStack(Fragment fragment, String tag, int id) {
     FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
     transaction.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
     transaction.add(id, fragment, tag);
     transaction.commitAllowingStateLoss();
}

Where tag might be String class name, id of your root view in activity (Because fragment should appear on the top layer).

In order to use the onBackPressed() method override in the Activity as you have in the question, you also need to add this to your Fragment:

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
      case android.R.id.home:
        // Assuming MainActivity is the Activity subclass name
        if (getActivity() instanceof MainActivity) {
            ((MainActivity) getActivity()).onBackPressed();
        }
        return true;
      default:
        return super.onOptionsItemSelected(item);
    }
}

In order to show/hide the back button, add these methods to your Activity:

public void showUpButton() {
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}

public void hideUpButton() {
    getSupportActionBar().setDisplayHomeAsUpEnabled(false);
}

Then, when you want to show or hide the back/up button from a Fragment, call these methods.

In your case, you could hide the back/up button from onResume() in Fragment 1:

((MainActivity) getActivity()).hideUpButton();

And then show it in onResume() in Fragment 2:

((MainActivity) getActivity()).showUpButton();

There are a lot of way to do this job. In my opinion the most elegant is the following. I would isolate the logic in each component. Every fragment implements an interface like "IBackHandler" that allows activity and fragment to communicate. In the activity onBackPressed asks first the fragment (if it is instantiated) what to do and then acts.

The interface:

public interface IBackHandler {
    boolean doBack();
}

The fragment that implements that interface and put its logic to handle the back button pressed:

public class YourFragment1 extends YourBaseFragment implements IBackHandler {
      // your code
      @Override
      public boolean doBack() {
           // return true means that you have done your stuff
           //and you don't want 'super.onBackPressed()' to be called
           return true; // this means do nothing
      }
 }

Fragment 2:

 public class YourFragment2 extends YourBaseFragment implements IBackHandler {
      // your code
      @Override
      public boolean doBack() {
           return false; //this means: call 'super.onBackPressed()'
      }
 }

Your Activity:

public class YourActivity extends YourBaseActivity {
     //your code
     @Override
     public void onBackPressed() {
         Fragment currentFragment = getFragmentManager().findFragmentById(R.id.yourFragment);
    if (currentFragment instanceof IBackHandler) {
        if (!((IBackHandler) currentFragment).doBack()) {
            super.onBackPressed();
        }
    } else
        super.onBackPressed();
     }
}

You could think that this is overengineering but I can reassure you that in this way you'll always be able to control what'happening in your flow.

Hope this help!

I solved this problem use this code when change fragment:

String fragmentIndexString="fragmenttwo";//or fragmentone something
transaction.addToBackStack();

This is full code in Activity:

FirstFragment firstFragment; // my first fragment
SecondFragment secondFragment; // my second fragment
public static String FIRST="asfasgasg"; //first fragment index
public static String SECOND="gsadgsagd"; //second fragment index
...
/* u can change fragment by using setFragment funiction */
public void setFragment(String page){
    FragmentTransaction transaction = fragmentManager.beginTransaction();
    switch (page){
        case FIRST:
            if(firstFragment==null) firstFragment= SettingFragment.newInstance();
            if (!firstFragment.isAdded()) {
                transaction.replace(R.id.fragmentcontainer, firstFragment);
                transaction.addToBackStack(INDEX);
                transaction.commit();
            } else {
                transaction.show(firstFragment);
            }
            break;
        case SECOND:
            if(secondFragment==null) secondFragment= SettingFragment.newInstance();
            if (!secondFragment.isAdded()) {
                transaction.replace(R.id.fragmentcontainer, secondFragment);
                transaction.addToBackStack(INDEX);
                transaction.commit();
            } else {
                transaction.show(secondFragment);
            }
            break;
        default:
            setFragment(INDEX);
    }
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
    if(keyCode == KeyEvent.KEYCODE_BACK && event.getAction() == KeyEvent.ACTION_DOWN){
        if(fragmentManager.getBackStackEntryCount()>1){
            fragmentManager.popBackStack();
            return true;
        }
    }
    return super.onKeyDown(keyCode, event);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM