9

In a Fragment, called within an activity I'm displaying a list of bus lines like this:

Page 1, when opening for the first time.

Then, once the user clicks on "Stations", I like to show a list of stations of course. I'm using this code:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    setContentView(R.layout.act_long_distance);

    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.add(R.id.f_long_distance, new LongDistanceFragment()).commit();
}

@SuppressWarnings({"UnusedDeclaration"})
public void showStationList(View view) {
    String tag = (String) view.getTag();
    if (tag != null && tag.length() > 0) {
        FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
        StationListFragment fragment = new StationListFragment(tag.split(","));
        ft.add(R.id.f_long_distance, fragment);
        // ft.replace(R.id.f_long_distance, fragment);
        ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_FADE);
        ft.addToBackStack(null);
        ft.commit();
    }
}

The XML for this activity is:

<LinearLayout
    android:id="@+id/ll_container"
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical"
    >
    <FrameLayout
        android:id="@+id/f_long_distance"
        android:layout_weight="1"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        />
</LinearLayout>

StationListFragment is a simple ListFragment displayed on top of the other:

After clicking on the Station List button

What works well though is the ActionBar, it now properly contains the Title only.

What doesn't work is if I press back now. The Station List is hidden, but the old ActionBar is not restored:

ActionBar after coming back from List button

The docs are saying that the way to add the ActionBar is using onCreateOptionsMenu methods etc.

So, in LongDistanceFragment (the first one shown), I'm creating the bar like this:

@Override
public void onViewCreated(View view, Bundle savedInstanceState) {
    Log.d(TAG, "onViewCreated");
    super.onViewCreated(view, savedInstanceState);

    setHasOptionsMenu(true);
}

@Override
public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
    super.onCreateOptionsMenu(menu, inflater);

    ActionBar bar = getSupportActivity().getSupportActionBar();
    bar.setNavigationMode(ActionBar.NAVIGATION_MODE_LIST);
    bar.setListNavigationCallbacks(new SimpleSpinnerArrayAdapter(getActivity()), this);
}

But somehow it is not restored once the user is back in that Fragment.

I think a way to recover the state of the ActionBar when rolling back the Fragment Transaction is needed.

What am I missing? Thanks for any help.

Sebastian Roth
  • 11,344
  • 14
  • 61
  • 110
  • I am battling with this at the moment too. Here is a related question. http://stackoverflow.com/questions/6503189/fragments-onresume-from-back-stack – Manfred Moser Jan 05 '12 at 22:17

2 Answers2

9

If I understand your code correctly, the problem is likely within your StationListFragment.

The ActionBar is associated with the Activity itself, not a particular Fragment within it.

I'm guessing that within the StationListFragment you're modifying the ActionBar to display the "Stations" title and disable the List navigation mode. In that case, pressing the back button undoes the transaction -- effectively removing the StationListFragment -- but doesn't automagically undo any changes you might have made to the Activity's Action Bar.

What you'll need to do is override one of the state change handlers within your Station List Fragment to undo the ActionBar changes when it's removed / hidden.

A better approach would be to use a replace transaction to exchange the LongDistanceFragment with the StationListFragment (rather than adding the latter on top of the former.) Then you can add the code to configure the Action Bar to each Fragment so they set it up appropriately when they become visible (by overriding onResume) rather than trying to clean up after one's been removed.

Reto Meier
  • 96,655
  • 18
  • 100
  • 72
  • 2
    None of the state change handlers in the ListFragment is actually called at all so you have no way of doing that. That is imho a miss in the API. – Manfred Moser Jan 05 '12 at 22:58
  • 1
    I am using replace but I am adding the detail view to the back stack. And then when the back button is pressed no event is fired on the list to be able to reset the title back.. – Manfred Moser Jan 05 '12 at 23:03
  • Then where is he changing the ActionBar title? Based on the code in this sample it should never display "Bus Line Stops" - I have to assume that's happening in the StationListFragment. – Reto Meier Jan 05 '12 at 23:03
  • But where are you changing it to begin with? – Reto Meier Jan 05 '12 at 23:04
  • 1
    In my case each fragment sets the title in onResume but when going back to the list onResume is not called so it stays at the detail title. Nothing seems to be called when using back. – Manfred Moser Jan 05 '12 at 23:15
  • Dear Reto & Manfred: After doing more work with the Fragments I concluded that the ActionBar state & behavior is best managed from within the Fragment as the sole authority. Esp. if this later moves to Tablets. 2nd, I changed my code to be more lean. Activities that simply manage "child fragments" will use FragmentTransaction.replace on `android.R.id.content`. Thanks both of u. – Sebastian Roth Jan 07 '12 at 11:23
  • Hey can you tell me how to update actiobar title while change the fragment in tabpager.? – Suresh Parmar Oct 03 '14 at 08:00
1

I was dealing with the same problem and when I revert changes to ActionBar in the onStop method of the second Fragment, it works fine.

David Vávra
  • 18,446
  • 7
  • 48
  • 56