我对android片段Backstack的工作方式遇到了一个很大的问题,对于提供的任何帮助将不胜感激。
假设您有3个片段[1] [2] [3]
我希望用户能够导航[1] > [2] > [3]
,但在返回的途中(按返回按钮)[3] > [1]
。
就像我想象的那样,这将通过在创建将片段addToBackStack(..)
带入XML定义的片段持有者的事务时不调用[2]
来实现。
现实情况似乎是,如果我不希望当用户在[2]
上按“后退”按钮时再次显示[3]
,则我不能在显示片段addToBackStack
的事务中调用[3]
。这似乎完全违反直觉(也许来自iOS世界)。
无论如何,如果我这样做,当我从[1] > [2]
转到并按回去时,我会按预期返回[1]
。
如果我输入[1] > [2] > [3]
,然后按回去,则跳回[1]
(如预期)。
现在,当我尝试从[2]
再次跳转到[1]
时,就会发生奇怪的行为。首先,在显示[3]
之前简要显示[2]
。如果此时我按回去,则显示[3]
,如果再次按回去,则应用程序退出。
谁能帮我了解这里的事吗?
这是我的主要 Activity 的布局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();
//Create third fragment, Dont add this transaction to the backstack, because we dont want to go back to [2]
frag = new Fragment3();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.commit();
//END OF SETUP CODE-------------------------
//NOW:
//Press back once and then issue the following code:
frag = new Fragment2();
transaction = getSupportFragmentManager().beginTransaction();
transaction.replace(R.id.detailFragment, frag);
transaction.addToBackStack(null);
transaction.commit();
//Now press back again and you end up at fragment [3] not [1]
非常感谢
最佳答案
说明:这是怎么回事?
如果我们牢记.replace()
与文档中知道的.remove().add()
相等:
那么发生的事情是这样的(我在碎片中添加数字以使其更清楚):
// transaction.replace(R.id.detailFragment, frag1);
Transaction.remove(null).add(frag1) // frag1 on view
// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);
Transaction.remove(frag1).add(frag2).addToBackStack(null) // frag2 on view
// transaction.replace(R.id.detailFragment, frag3);
Transaction.remove(frag2).add(frag3) // 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 view
Transaction.remove(null).add(frag1) //frag1, frag3 on view (OVERLAPPING)
// transaction.replace(R.id.detailFragment, frag2).addToBackStack(null);
Transaction.remove(frag3).add(frag2).addToBackStack(null) //frag2 on view
< press back button >
// system makes saved transaction backward
Transaction.remove(frag2).add(frag3) //frag3 on view
< press back button >
// no more entries in BackStack
< app exits >
可能的解决方案
考虑实现
FragmentManager.BackStackChangedListener
来监视后向堆栈中的更改,并在 onBackStackChanged()
方法中应用您的逻辑:FragmentTransaction.addToBackStack(String name);