9

I'm building a pretty simple app. At it's core are 2 screens:
1) list-screen: a list of items
2) detail-screen: a detailed view of an item

I used one Activity (which extends AppCompatActivity) with an Action-Bar, a Navigation-Drawer and a main-content part (a FrameLayout).
I used 2 different fragments for the 2 screens:

When opening the app I inflate the list-fragment into the main-content part.
When an item in the list is clicked I inflate the detail-fragment into the main-content part and it all works well. My App Layout
On the detail-screen I want the Action-Bar to display an up-button that goes back to the list-screen.
Considering the fact that I am using fragments, rather than separate activites, how can I achieve that?

BeFree
  • 469
  • 1
  • 7
  • 15
  • [`Fragment#getActivity()`](http://developer.android.com/reference/android/app/Fragment.html#getActivity()) to get the Activity? Also there is [Implement Back Navigation for Fragments](http://developer.android.com/training/implementing-navigation/temporal.html#back-fragments) – OneCricketeer Dec 01 '15 at 17:15
  • Thanks, but I'm referring to the up button (see the top left caret on the rightmost sketch above) - not the back button – BeFree Dec 02 '15 at 09:46

1 Answers1

13

You can enable the up button each time the Detail Fragment loads, and disable it whenever any of the other Fragments load.

First define these methods in your Activity, which you can call from the Fragments in order to show/hide the up button:

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

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

You will probably want to just enable the up button in on Resume() of the detail Fragment (MainActivity is just an example, change to the name of your Activity) .....

@Override
public void onResume() {
    super.onResume();
    MainActivity activity = (MainActivity)getActivity();
    if (activity != null) {
      activity.showUpButton();
    }

}

Then in the other Fragments:

@Override
public void onResume() {
    super.onResume();
    MainActivity activity = (MainActivity)getActivity();
    if (activity != null) {
      activity.hideUpButton();
    }

}

The next thing is to make the up button actually go back. First ensure that you're adding the Fragment with the up button to the back stack, and then add this to that Fragment.

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
    case android.R.id.home:
        ((MainActivity)getActivity()).onBackPressed();
        return true;
    default:
        return super.onOptionsItemSelected(item);
    }
}

Then in the Activity, override onBackPressed() and pop from the back stack if the FragmentManager has any entries:

@Override
public void onBackPressed() {

    FragmentManager fragmentManager = getSupportFragmentManager();
    if (fragmentManager.getBackStackEntryCount() > 1) {
        fragmentManager.popBackStackImmediate();
    } else {
        super.onBackPressed();
    }
}
Daniel Nugent
  • 43,104
  • 15
  • 109
  • 137
  • Thanks, I'll try it, but it will only solve half my problem as I also need a way to tell each fragment who's the hierarchical parent. If I would use activities, instead of fragments I could simply define the List activity as the parent of the detail activity and it would all work nicely. The reason I don't do that is because the transitions are much smoother with fragments – BeFree Dec 02 '15 at 09:50
  • @befree you're right, I had forgotten about one last thing (just added to the answer), however you don't need to tell Fragments who their parent is as you do with Activities. – Daniel Nugent Dec 02 '15 at 10:30
  • @BeFree one more edit, you'll also need the onBackPressed() override in the Activity. – Daniel Nugent Dec 02 '15 at 10:54
  • 1
    Perfect, it works. Since I also use a navigation drawer and use the ActionBarDrawerToggle component I also needed to add these calls inside showUpButton: toggle.setDrawerIndicatorEnabled(false); toggle.setToolbarNavigationClickListener(...); – BeFree Dec 02 '15 at 11:13
  • 1
    I have tried this. It's not working as expected. In the inner fragment, home button changes to Back button, but still it acts like the same old menu button. When you press the system back and reach back home screen, the home icon disappears. I ended up with these two issues. – Ajith M A Apr 12 '16 at 10:28
  • 2
    onOptionsItemSelected in the fragment will not be called unless you also add a call to setHasOptionsMenu(true) when the fragment is first created. – Monte Creasor Jun 10 '18 at 21:23