4

为什么会FragmentTwo在以下情况下从后台消失:

  • 我的应用程序有一个Fragment被调用FragmentOneActivity.
  • FragmentOne持有一个Button。单击时,它会启动FragmentTwo,并将其添加到Fragmentbackstack 中。
  • FragmentTwo有一个Button,当单击它时,将两个选项卡添加到ActionBar链接到两个的FragmentsFragmentThreeFragmentFourFragmentThree可见。
  • 如果我现在单击后退按钮,我希望看到FragmentTwo. 相反,我看到FragmentOne. 去哪儿了FragmentTwo

在我覆盖onKeyDown()并开始实现我自己的后台堆栈之前,Fragments我想问一下我是否缺少明显的东西?请注意,在测试时不会发生配置更改。

在此处输入链接描述

细节:

FragmentOne 的按钮单击处理程序包含:

    FragmentTransaction ft = getFragmentManager().beginTransaction();
    FragmentTwo fragment = new FragmentTwo();
    ft.addToBackStack(null);
    ft.replace(android.R.id.content, fragment).commit();

FragmentTwo 按钮点击在 Activity 中处理:

    getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_TABS);
    FragmentFour fragmentThree = new FragmentThree();
    FragmentFive fragmentFive = new FragmentFive();

    ActionBar.Tab tab = getActionBar().newTab().setText("Frag 3").setTabListener(new CustomTabListener<FragmentThree>(fragmentThree));
    getActionBar().addTab(tab);
    tab = getActionBar().newTab().setText("Frag 4").setTabListener(new CustomTabListener<FragmentFour>(fragmentFour));
    getActionBar().addTab(tab);

选项卡侦听器在哪里:

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) {
        ft.replace(android.R.id.content, fragment);
    }

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

    public void onTabReselected(Tab tab, FragmentTransaction ft) {

    }
}

我如果在显示Fragments之前添加更多到 backstack FragmentThree,它总是并且只有FragmentFragmentThree一个消失了。

当我通过按返回键离开选项卡式用户视图并返回时FragmentOne,选项卡仍在显示。我知道我需要将 重置ActionBarNAVIGATION_MODE_STANDARD,但不清楚为什么FragmentOne显示而不是FragmentTwo.

4

5 回答 5

2

我认为问题是如果你建立你的标签

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

被调用并且之前的片段不被添加到后台堆栈

你试过打电话吗

ft.addToBackStack(null);

在片段二按钮处理代码中。

但是您无论如何都需要实施onBackPressed()以摆脱标签。我想我会用标签进行新的活动。

于 2013-01-08T14:39:44.353 回答
2

@Pierre Rymiortz,我刚刚解决了这个问题。请参考下面的代码。

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();
    }
}

}
于 2013-08-07T13:34:26.850 回答
1

我认为你需要删除函数ft.remove中的,onTabUnselected()因为替换已经这样做了。

于 2013-01-16T22:12:09.467 回答
1

始终使用此代码块替换片段:

FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
ft.replace(android.R.id.content, YOUR_FRAGMENT);
ft.addToBackStack(null);
ft.commit();
于 2013-01-10T23:34:43.767 回答
1

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.

于 2013-01-17T22:51:17.970 回答