片段addToBackStack()和popBackStackImmediate()不起作用

时间:2014-11-01 22:07:56

标签: android android-fragments back-stack

我目前正在使用一个ActionBarActivity和更多Fragments构建Android应用程序(14< = SDK< = 21),例如ListFragment和{{1} },在单个MapFragment视图中交换。

ActionBarActivity自动替换/提交片段A.然后,当用户点击一个按钮时,托管活动替换/提交一个新的不同片段B.我的目标是让用户在按下后立即返回片段A.后退按钮。

现在有些代码。

MainActivity

FrameLayout


问题

即使调用public class MainActivity extends ActionBarActivity implements StopFragment.OnFragmentInteractionListener, StopItemFragment.OnFragmentInteractionListener { ... @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); fragmentManager = getFragmentManager(); fragmentManager.enableDebugLogging(true); ... if (fragmentManager.findFragmentById(R.id.content_frame) == null) { StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment fragmentManager.beginTransaction() .replace(R.id.content_frame, list) .addToBackStack(null) .commit(); } ... @Override public void onFragmentInteraction(String id) { selectItem(Integer.parseInt(id)); } private void selectItem(int position) { StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment ... fragmentManager.beginTransaction() .replace(R.id.content_frame, fragment) .commit(); ... } } ,当我在片段B上时,我也无法返回片段A. MainActivity直接关闭。 然而,我试图自己管理背堆,没有运气。我可以看到片段在堆栈上但是如果我调用addToBackStack(),则弹出片段A并且不执行片段事务。 (先回来什么都没发生,第二次活动关闭)

我还附加了FragmentManager logcat:
http://pastebin.com/hFLHprL8

6 个答案:

答案 0 :(得分:71)

对于那些仍在寻找解决方案的人。

在主Activity类(托管片段)中,只需覆盖onBackPressed()

@Override
public void onBackPressed() {
    if (getFragmentManager().getBackStackEntryCount() > 0 ){
        getFragmentManager().popBackStack();
    } else {
        super.onBackPressed();
    }
}

片段中没有onBackPressed()方法,此方法仅适用于activity。因此,当我们按后退键时,会显示activity的默认行为,即

  

您将转到之前的活动(如果有)或应用程序   将退出。

现在我们需要覆盖这个方法来告诉activity当我们按下后退键时,如果后面的堆栈中有任何片段,则将它们弹出(这是addToBackStack()到来的时候进入图片)。否则,请遵循默认行为。

答案 1 :(得分:5)

试试这个(注意添加而非替换表示fragmentA, addToBackStack()表示fragmentB)

StopItemFragment list = StopItemFragment.newInstance(null); //A - extends ListFragment
        fragmentManager.beginTransaction()
            .add(R.id.content_frame, list)
            .commit();

StopFragment fragment = StopFragment.newInstance(null, null); //B - extends Fragment
   ...
   fragmentManager.beginTransaction()
        .replace(R.id.content_frame, fragment)
        .addToBackStack("FragmentB")
        .commit();

答案 2 :(得分:5)

我必须手动拨打beginTransaction()的{​​{1}}和commit() 通过覆盖FragmentManager解决:

onBackPressed()

答案 3 :(得分:1)

如果你正在与addToBackStack()& popBackStack()然后只需使用

FragmentTransaction ft =getSupportFragmentManager().beginTransaction();
ft.replace(R.id.content_frame, new HomeFragment(), "Home");
ft.commit();`

在你的活动中OnBackPressed()通过标签找出fargment然后做你的东西

Fragment home = getSupportFragmentManager().findFragmentByTag("Home");

if (home instanceof HomeFragment && home.isVisible()) {
    // do you stuff
}

更多信息https://github.com/DattaHujare/NavigationDrawer  我从不使用addToBackStack()来处理片段。

答案 4 :(得分:0)

popBackStack()popBackStackImmediatly()的原因是你没有将该片段(你要弹出)添加到backStack。为此,您必须在使事务添加/替换片段时调用addToBackStack()。

答案 5 :(得分:0)

首先,我想对突出显示的[Nick]的回答表示感谢(低声望不能在下面发表评论),因为它帮助我知道确实存在一些未提及的问题。 Android文档。

第二,现在是2019年,在Androidx的“偏好设置”中尝试了类似的方式后,我很长一段时间都找不到任何东西,直到我同时检查了这个问题和一个official sample code in Kotlin,这个问题导致一个线索,示例代码的方式实际上就是我的解决方案,就像一个魅力,只有很小的覆盖,希望它对那些正在寻找正式解决方案的人也有帮助

@Override
public boolean onSupportNavigateUp() {

    if (getSupportFragmentManager().popBackStackImmediate()){
        return true;
    }

    return super.onSupportNavigateUp();
}

Aforementioned code in Java (Screenshot)

P.S。在使用至少5年以上之后,我对stacksoverflow的第一个回答^^