片段从后台消失

时间:2013-01-08 06:48:04

标签: android android-fragments android-actionbar android-tabs

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

  • 我的应用在Fragment中有一个名为FragmentOne的{​​{1}}。
  • Activity拥有FragmentOne。单击时,它会启动Button,并将其添加到FragmentTwo后台堆栈中。
  • Fragment有一个FragmentTwo,点击后会为与ButtonActionBarFragments相关联的FragmentThree添加两个标签。 FragmentFour可见。
  • 如果我现在点击后退按钮,我希望看到FragmentThree。相反,我看到FragmentTwoFragmentOne去了哪里?

在我覆盖FragmentTwo并开始为onKeyDown()开始实施我自己的后台包装之前,我想问一下我是否遗漏了一些明显的东西?请注意,测试时没有发生配置更改。

enter link description here

详细说明:

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

Fragments

FragmentTwo按钮单击在Activity:

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

标签监听器的位置是:

    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) { } } 之前向backstack添加更多Fragments,则始终只有FragmentThree之前Fragment消失。

当我通过按后退键离开选项卡式用户视图并返回FragmentThree时,标签仍然显示。我了解到我需要将FragmentOne重置为ActionBar,但不清楚为什么显示NAVIGATION_MODE_STANDARD而不是FragmentOne

5 个答案:

答案 0 :(得分:2)

我认为问题在于你是否构建了标签

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

并将之前的片段添加到backstack

你打算试试

吗?
ft.addToBackStack(null);

在Fragment Two按钮处理代码中。

但是你需要实现onBackPressed()来摆脱标签。我想我会用标签进行新的活动。

答案 1 :(得分: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();
    }
}

}

答案 2 :(得分:1)

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

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

答案 3 :(得分:1)

我认为您需要删除ft.remove函数中的onTabUnselected(),因为替换已经执行此操作。

答案 4 :(得分:1)

根据您上面显示的代码,您永远不会将Fragment2添加到后台堆栈。

@gabe,@ Piier,API http://developer.android.com/reference/android/app/ActionBar.TabListener.html

中记录了在侦听器中使用addToBackStack()获取IllegalStateException的原因
public abstract void onTabSelected (ActionBar.Tab tab, FragmentTransaction ft)  
  

在API级别11中添加

     

当标签进入选定状态时调用。

     

“参数”选项卡已选择的选项卡

     

ft FragmentTransaction,用于排序在选项卡切换期间执行的片段操作。上一个选项卡未选中,此选项卡的选择将在单个事务中执行。

     

此FragmentTransaction不支持添加到后台堆栈。

解决这个问题的简单方法是使用FragmentManager在TabListener中创建自己的FragmentTransaction并将其添加到后台堆栈。像这样的东西

    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) {

    }
}

我只修改了onTabSelected,但你明白了。此外,请不要忘记commit()此交易,因为听众只会自动commit()提供的FragmentTransaction ft

最后一件事,确保在执行事务后调用addToBackStack(),因为这是您要添加到堆栈的内容,而不是实际的片段。在上面的代码中,没有为Fragment1的按钮单击完成。

希望这有帮助。