lionelmessi
lionelmessi

Reputation: 1144

FragmentManager pushing back button exits the app

Please refer to this question for the setup of fragments:

|  A  |  B  |
         ↓
   |  C  |  D  |
      ↓
   |  E  |

I am struggling to figure out why my App is exiting on pressing the back button on a fragment added with addToBackStack().

According to the answer,

Case 1: If I use getSupportFragmentManager() or getFragmentManager(): my fragments vanish after I swipe to a different tab and come back.

Case 2: if I use getChildFragmentManager(): I dynamically add Fragment E to C while using addToBackStack() but when I press back, the app exits. Expectation is that it should return to C instead of exiting.

Code for adding tabs C and D is:

public class MyProfileTabFragmentPagerAdapter extends FragmentPagerAdapter {
private String tabTitles[];
private Context context;
private String userID;

private static final String TAG = makeLogTag(MyProfileTabFragmentPagerAdapter.class);
public MyProfileTabFragmentPagerAdapter(FragmentManager fm, Context context) {
    super(fm);
    tabTitles = context.getResources().getStringArray(R.array.profileTabs);
    this.context = context;
    SharedPreferences prefs =
            PreferenceManager.getDefaultSharedPreferences(context);

    userID = prefs.getString("token", "");
}

@Override
public int getCount() {
    return tabTitles.length;
}

@Override
public Fragment getItem(int position) {
    switch (position){
        case 0:
        {
            return UserProfileFragment.getInstance(userID);
        }
        case 1:
        {
            return new MySnapsFragment();
        }

        default:
        {
            LOGI(TAG, "Invalid tab" + position);
            return null;
        }
    }
}

@Override
public CharSequence getPageTitle(int position) {
    // Generate title based on item position
    return tabTitles[position];
  }
}

This is how I setup my tabs in B which I call in its onCreateView():

private void setupTabs() {
  // Get the ViewPager and set it's PagerAdapter so that it can display items
  vpProfileTab.setAdapter(new MyProfileTabFragmentPagerAdapter(getChildFragmentManager(), ctx));

  // Give the TabLayout the ViewPager
  slidingProfileTabs.setDistributeEvenly(true);
  slidingProfileTabs.setBackgroundColor(colorAccent2);
  slidingProfileTabs.setSelectedIndicatorColors(colorTabIndicator);
  slidingProfileTabs.setViewPager(vpProfileTab);
}

I setup C from B using in onCreateView():

    private void setupUserProfileFeed() {
    if(feedFragment==null){
        feedFragment = new FeedFragment();
        this.getFragmentManager().beginTransaction().replace(R.id.feed_fragment, feedFragment).addToBackStack()
                .commit();
    }
}

I setup E from C when I click a button:

@Override
public void onProfileClick(View v) {
    UserProfileFragment userProfileFragment = UserProfileFragment.getInstance(userID);

    this.getFragmentManager().beginTransaction().replace(R.id.feedContent, userProfileFragment)
            .addToBackStack(null).commit();
}

I am using SlidingTabLayout from Google github here.

I have the following questions:

  1. What is the reason for Case 1. Which FM should be used, as per my understanding: getFM() should be used for top level and getChildFM() should be used for adding fragments to a fragment?
  2. Why is the App exiting in Case 2? Do I need to do anything else?
  3. How to solve this problem either way? Have been stuck for a while, any help is highly appreciated.

Upvotes: 0

Views: 193

Answers (1)

Taylor Courtney
Taylor Courtney

Reputation: 813

override onBackPressed and make a switch statement for the different view pager positions (0,1,2,3...) and tell it what to do in each case. Add this to the main activity where you are attaching the viewPager adapter. This example code is a simple way to do it if you want more complex behavior use the switch statement as previously described.

@Override public void onBackPressed() { if (mViewPager.getCurrentItem() == 0) { // If the user is currently looking at the first page, allow android to handle the // Back button. This exits the app because you are on the first fragment. super.onBackPressed(); } else { // Otherwise, select the fragment in the viewPager mViewPager.setCurrentItem(mViewPager.getCurrentItem() - 1); } }

Upvotes: 1

Related Questions