Android Fragment Back Stack的问题

我对android片段Backstack的工作方式遇到了一个很大的问题,对于提供的任何帮助将不胜感激。


假设您有3个片段


[1] [2] [3]


我希望用户能够导航[1] > [2] > [3]但在返回的途中(按返回按钮)[3] > [1]。


就像我想象的那样,这可以通过addToBackStack(..)在创建将片段[2]带入XML定义的片段持有者的事务时不调用来实现。


现实情况似乎是,如果我不想[2]在用户按下“后退”按钮时再次出现[3],则我不能调用addToBackStack显示片段的事务[3]。这似乎完全违反直觉(也许来自iOS世界)。


无论如何,如果我这样做,当我离开[1] > [2]并按回去时,我会按[1]预期到达。


如果我走了[1] > [2] > [3]然后按回去,我跳回了[1](按预期)。现在,当我尝试[2]从再次跳到时,就会发生奇怪的行为[1]。首先在[3]显示之前简要显示[2]。如果此时我按回,[3]将显示,如果我再次按回,则该应用程序退出。


谁能帮我了解这里的事吗?



这是我的主要活动的布局xml文件: 


<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"

          android:layout_width="fill_parent"

          android:layout_height="fill_parent"

          android:orientation="vertical" >


<fragment

        android:id="@+id/headerFragment"

        android:layout_width="match_parent"

        android:layout_height="wrap_content"

        class="com.fragment_test.FragmentControls" >

    <!-- Preview: layout=@layout/details -->

</fragment>

<FrameLayout

        android:id="@+id/detailFragment"

        android:layout_width="match_parent"

        android:layout_height="fill_parent"


        />




更新 这是我用来通过导航继承构建的代码


    Fragment frag;

    FragmentTransaction transaction;



    //Create The first fragment [1], add it to the view, BUT Dont add the transaction to the backstack

    frag = new Fragment1();


    transaction = getSupportFragmentManager().beginTransaction();

    transaction.replace(R.id.detailFragment, frag);

    transaction.commit();


    //Create the second [2] fragment, add it to the view and add the transaction that replaces the first fragment to the backstack

    frag = new Fragment2();


    transaction = getSupportFragmentManager().beginTransaction();

    transaction.replace(R.id.detailFragment, frag);

    transaction.addToBackStack(null);

    transaction.commit();

牧羊人nacy
浏览 411回答 3
3回答

慕仙森

说明:这是怎么回事?如果我们牢记这.replace()一点.remove().add(),我们将通过文档了解这一点:替换添加到容器中的现有片段。这本质上与调用remove(Fragment)所有当前添加的片段相同,这些片段在此处添加了相同的参数containerViewId,然后又add(int, Fragment, String)添加了相同的参数。然后发生的事情是这样的(我在片段中添加数字以使其更清楚):// transaction.replace(R.id.detailFragment, frag1);Transaction.remove(null).add(frag1)&nbsp; // frag1 on view// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);Transaction.remove(frag1).add(frag2).addToBackStack(null)&nbsp; // frag2 on view// transaction.replace(R.id.detailFragment, frag3);Transaction.remove(frag2).add(frag3)&nbsp; // frag3 on view(这里所有误导性的东西开始发生)请记住,.addToBackStack()只保存事务而不保存片段本身!所以现在我们有了frag3布局:< press back button >// System pops the back stack and find the following saved back entry to be reversed:// [Transaction.remove(frag1).add(frag2)]// so the system makes that transaction backward!!!// tries to remove frag2 (is not there, so it ignores) and re-add(frag1)// make notice that system doesn't realise that there's a frag3 and does nothing with it// so it still there attached to viewTransaction.remove(null).add(frag1) //frag1, frag3 on view (OVERLAPPING)// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);Transaction.remove(frag3).add(frag2).addToBackStack(null)&nbsp; //frag2 on view< press back button >// system makes saved transaction backwardTransaction.remove(frag2).add(frag3) //frag3 on view< press back button >// no more entries in BackStack< app exits >可能的解决方案考虑实现FragmentManager.BackStackChangedListener以观察后向堆栈中的更改,并在onBackStackChanged()methode中应用您的逻辑:跟踪交易计数;通过名称检查特定交易 FragmentTransaction.addToBackStack(String name);等等。

慕尼黑8549860

对!!!经过多拉头发,我终于弄清楚了如何使其正常工作。似乎在按下后退按钮时并未从视图中删除片段[3],因此您必须手动进行操作!首先,不要使用replace(),而要分别使用remove和add。似乎replace()无法正常工作。下一步是重写onKeyDown方法,并在每次按下后退按钮时删除当前片段。@Overridepublic boolean onKeyDown(int keyCode, KeyEvent event){&nbsp; &nbsp; if (keyCode == KeyEvent.KEYCODE_BACK)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; if (getSupportFragmentManager().getBackStackEntryCount() == 0)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; this.finish();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; else&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; getSupportFragmentManager().popBackStack();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; removeCurrentFragment();&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return false;&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; return super.onKeyDown(keyCode, event);}public void removeCurrentFragment(){&nbsp; &nbsp; FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();&nbsp; &nbsp; Fragment currentFrag =&nbsp; getSupportFragmentManager().findFragmentById(R.id.detailFragment);&nbsp; &nbsp; String fragName = "NONE";&nbsp; &nbsp; if (currentFrag!=null)&nbsp; &nbsp; &nbsp; &nbsp; fragName = currentFrag.getClass().getSimpleName();&nbsp; &nbsp; if (currentFrag != null)&nbsp; &nbsp; &nbsp; &nbsp; transaction.remove(currentFrag);&nbsp; &nbsp; transaction.commit();}希望这可以帮助!
打开App,查看更多内容
随时随地看视频慕课网APP