Fragment disappears from backstack

為{幸葍}努か 提交于 2019-12-05 13:30:23

I think the problem is if you build your tabs

public void onTabSelected(Tab tab, FragmentTransaction ft) {
    ft.replace(android.R.id.content, fragment);
}

gets called and the fragment before is not added to the backstack

did you try to call

ft.addToBackStack(null);

in the Fragment Two button handling code.

But you need to implement onBackPressed() anyway to get rid of the tabs. I think I would make new activity with tabs.

lakshman

@Pierre Rymiortz, i just did the workaround for the Issue. please refer the Code below.

public class StartActivity extends SherlockFragmentActivity implements
    TabListener, OnBackStackChangedListener {

private Context mContext = null;

private ActionBar mActionBar;

private Tab mTab;

private Fragment mSelectFragment;

private final static int ONE = 0;
private final static int TWO = 1;
private final static int THREE = 2;
private final static int PLAYERS = 3;

private MenuItem mPlayerItem = null;

private FragmentTransaction mFragmentTransaction = null;

/**
 * by default is false - TABS were taken in the starting true - when we are
 * changing back to TABS from STANDARD
 */
private boolean mTabsChanges = false;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mContext = this;

    mActionBar = getSupportActionBar();

    // hiding the ActionBar icon
    mActionBar.setDisplayShowHomeEnabled(true);

    // for displaying the Arrow button
    mActionBar.setDisplayHomeAsUpEnabled(true);

    // hide Actionbar title
    mActionBar.setDisplayShowTitleEnabled(true);

    // Create Actionbar Tabs
    mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);

    // Create first Tab
    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("One");
    mActionBar.addTab(mTab);

    // Create Second Tab

    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("Two");
    mActionBar.addTab(mTab);

    // Create Three Tab
    mTab = mActionBar.newTab().setTabListener(this);
    mTab.setText("Three");
    mActionBar.addTab(mTab);

    getSupportFragmentManager().addOnBackStackChangedListener(this);

}

@Override
public void onTabSelected(Tab tab, FragmentTransaction ft) {
    mFragmentTransaction = ft;
    if (mTabsChanges) {
        // nothing to do here
        mTabsChanges = false;
    } else {
        switch (mActionBar.getSelectedNavigationIndex()) {
        case ONE:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment1();
            ft.replace(R.id.fragment_container, mSelectFragment, ONE + "");
            break;
        case TWO:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment2();
            ft.replace(R.id.fragment_container, mSelectFragment, TWO + "");
            break;
        case THREE:
            clearBackStack(mTabsChanges);
            mSelectFragment = new Fragment3();
            ft.replace(R.id.fragment_container, mSelectFragment, THREE + "");
            break;
        }
    }

}

@Override
public void onTabUnselected(Tab tab, FragmentTransaction ft) {
    Toast.makeText(
            mContext,
            "tab unselected." + mActionBar.getSelectedNavigationIndex()
                    + "", Toast.LENGTH_SHORT).show();
}

@Override
public void onTabReselected(Tab tab, FragmentTransaction ft) {
    Toast.makeText(
            mContext,
            "tab reselected." + mActionBar.getSelectedNavigationIndex()
                    + "", Toast.LENGTH_SHORT).show();
}

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    // TODO Auto-generated method stub
    MenuInflater mInflate = getSupportMenuInflater();
    mInflate.inflate(R.menu.header_menu, menu);

    mPlayerItem = menu.findItem(R.id.men_set_players);

    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    if (item.getItemId() == R.id.men_set_players) {
        addFragmentToStack();
        return true;
    }
    return false;
}

private void addFragmentToStack() {

    // Add the fragment to the activity, pushing this transaction
    // on to the back stack.
    mActionBar.setTitle(getResources().getString(R.string.menu_players));
    mSelectFragment = new PlayersFragment();
    FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
    ft.replace(R.id.fragment_container, mSelectFragment, "Players");
    ft.setTransition(FragmentTransaction.TRANSIT_FRAGMENT_OPEN);
    ft.addToBackStack("players");
    ft.commit();
}

@Override
public void onBackStackChanged() {
    FragmentManager fm = getSupportFragmentManager();
    if (fm.getBackStackEntryCount() > 0) {
        int TOP = fm.getBackStackEntryCount() - 1;
        Log.i("BACKSTACK", TOP + ".."
                + fm.getBackStackEntryAt(TOP).getName());
        if (fm.getBackStackEntryAt(TOP).getName()
                .equalsIgnoreCase("players")) {
            if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
                mTabsChanges = false;
                mActionBar
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_STANDARD);
            }
        } else {
            if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
                mTabsChanges = true;
                mActionBar
                        .setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
            }
        }

    } else {
        if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_STANDARD) {
            mTabsChanges = true;
            mActionBar.setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
        } else if (mActionBar.getNavigationMode() == ActionBar.NAVIGATION_MODE_TABS) {
            mTabsChanges = false;
        }
    }

    Toast.makeText(mContext,
            "FM Back count." + fm.getBackStackEntryCount(),
            Toast.LENGTH_SHORT).show();
}

public void clearBackStack(boolean callFromSelection) {
    if (!callFromSelection) {
        FragmentManager fm = getSupportFragmentManager();
        for (int i = 0; i < fm.getBackStackEntryCount(); i++) {
            fm.popBackStackImmediate();
        }
    } else {
        Toast.makeText(mContext, "callfromreapprearence",
                Toast.LENGTH_SHORT).show();
    }
}

}

Always use this code-block to replace fragment:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(android.R.id.content, YOUR_FRAGMENT);
ft.addToBackStack(null);
ft.commit();

I think you need to remove the ft.remove in the onTabUnselected() function since replace already does this.

According to the code you've shown above, you never add Fragment2 to the back stack.

@gabe, @Pierre, The reason you are getting an IllegalStateException by using addToBackStack() in the listener is documented in the API http://developer.android.com/reference/android/app/ActionBar.TabListener.html

public abstract void onTabSelected (ActionBar.Tab tab, FragmentTransaction ft)  

Added in API level 11

Called when a tab enters the selected state.

Parameters tab The tab that was selected

ft A FragmentTransaction for queuing fragment operations to execute during a tab switch. The previous tab's unselect and this tab's select will be executed in a single transaction.

This FragmentTransaction does not support being added to the back stack.

The easy way around this is to get your own FragmentTransaction inside the TabListener by using the FragmentManager and add it to the back stack. Something like this

    public static class CustomTabListener<T extends Fragment> implements TabListener {
    Fragment fragment;

    public CustomTabListener(Fragment fragment) {
        this.fragment = fragment;
    }

    public void onTabSelected(Tab tab, FragmentTransaction ft) {
        FragmentManager fm = getFragmentManager();
        FragmentTransaction newFragTrans = fm.beginTransaction();
        newFragTrans.replace(android.R.id.content, fragment);
        newFragTrans.addToBackStack(null);
        newFragTrans.commit()

    }

    public void onTabUnselected(Tab tab, FragmentTransaction ft) {
        ft.remove(fragment);
    }

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}

I only modified onTabSelected, but you get the point. Also, don't forget to commit() this transaction because the listener will only automatically commit() the supplied FragmentTransaction ft

One last thing, ensure you are calling addToBackStack() after performing your transaction, because that's what you are adding to the stack, rather than the actual fragment. In your code above this was not done for Fragment1's button click.

Hope this helps.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!