问题描述
|
是否可以在片段之间切换而无需始终重新创建片段?如果是这样,怎么办?
在文档中,我找到了一个如何替换片段的示例。
// Create new fragment and transaction
Fragment newFragment = new ExampleFragment();
FragmentTransaction transaction = getFragmentManager().beginTransaction();
// Replace whatever is in the fragment_container view with this fragment,// and add the transaction to the back stack
transaction.replace(R.id.fragment_container,newFragment);
transaction.addToBackStack(null);
// Commit the transaction
transaction.commit();
但是我不想每次都需要从头开始创建片段。
我还发现了隐藏/显示片段的示例:
// The content view embeds two fragments; Now retrieve them and attach
// their \"hide\" button.
FragmentManager fm = getFragmentManager();
addShowHideListener(R.id.frag1hide,fm.findFragmentById(R.id.fragment1));
addShowHideListener(R.id.frag2hide,fm.findFragmentById(R.id.fragment2));
但是,如何在XML文件外部创建一个ID为ID的片段?
我认为这可能与此问题有关,但没有答案。 :/
预先非常感谢您,
海蜇
编辑:
这就是我现在的做法:
Fragment shown = fragmentManager.findFragmentByTag(shownFragment);
//...
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (shown != null) fragmentTransaction.hide(shown);
//switch statetement for menu selection,just one example:
SettingsFragment set = (SettingsFragment) fragmentManager.findFragmentByTag(SET);
Toast.makeText(this,\"Settings:\" + set,Toast.LENGTH_LONG).show();
if (set == null)
{
set = new SettingsFragment();
fragmentTransaction.add(R.id.framelayout_content,set,SET);
}
else fragmentTransaction.show(set);
shownFragment = SET;
fragmentTransaction.commit();
如果我调出设置,然后再进行其他设置,然后再返回设置,则吐司首先给我“ null”,然后给我“ Settings:SettingsFragment {40ef ... \””。
但是,如果将fragmentTransaction.add(R.id.framelayout_content,SET);
替换为fragmentTransaction.replace(R.id.framelayout_content,SET);
,我会不断得到\“ null \”,\“ null \”,\“ null \” ...,因此似乎无法按标签找到Fragment。
编辑2:
加fragmentTransaction.addToBackStack(null);
就可以了。 :)
这样可以节省整个隐藏/存储哪个片段显示的部分,因此我认为这是最优雅的解决方案。
我发现本教程对该主题很有帮助。
编辑3:
通过查看代码,我意识到我可以摆脱一些部分,因此将其更改为:
FragmentTransaction fragmentTransaction = fragmentManager.beginTransaction();
if (shown != null) fragmentTransaction.hide(shown);
Settings set = (Settings) fragmentManager.findFragmentByTag(SET);
if (set == null) set = new Settings();
fragmentTransaction.replace(R.id.framelayout_content,SET);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();
但是,它调用了一个“ 7”,就像这里的一样。有防止这种情况的简便方法吗?否则,我想我可能会切换回隐藏/显示位。
解决方法
这可能取决于您要避免重新创建的内容。
// Replace whatever is in the fragment_container view with this fragment,// and add the transaction to the back stack
transaction.replace(R.id.fragment_container,newFragment);
transaction.addToBackStack(null);
在您的示例示例中,当您从newFragment中单击“后退”按钮时,将显示先前的片段(您将获得一个onCreateView,onActivityCreated但没有onCreate),因此不会像这样重新创建该片段。至于newFragment,如果您打算再次使用它,则仍然可以保留它,以根据onCreate或onActivityCreated中的要求更新任何内部状态。
编辑:
如果您仅具有一个菜单列表,每个条目都在右窗格中调用一个不同的片段,那么添加到后堆栈并不是您想要的。为此,您可以预先在每个片段上调用ѭ9,而不必根据需要隐藏/显示每个片段(我尚未对此进行测试)。否则,我建议持有对每个片段的引用,在选择其他菜单项时调用ѭ10,以确保您不添加到后堆栈中。
, 为了避免
IllegalStateException:片段
已经加入
我发现一种变通的解决方案对我来说很好:在交易中使用remove(AFrag)
和add(BFrag)
,而不是replace()
。
看来这是个错误:已接受答案中的第4条评论。
, fragmentTransactionOnClick.setTransition(FragmentTransaction.TRANSIT_EXIT_MASK);
如果您添加.setTransition.exit transit_exit_mask
,那么以前的视图就不会出现
, 我找到了一种使用\“ tag \”函数的方法:
//...
fragmentTransaction.add(R.id.framelayout_content,fragment1,\"foo\");
fragmentTransaction.add(R.id.framelayout_content,fragment2,\"bar\");
//...
fragmentManager.findFragmentByTag(\"foo\");
fragmentManager.findFragmentByTag(\"bar\");
但是,这似乎有点异步。在commit
之后立即调用findFragmentByTag
将返回null
。直到后来,以我为例,发生了“ѭ20”事件,才发现了碎片。
还有一个称为findFragmentById(int)
的函数,但不是很有用。如果未在XML布局中指定ID,则该ID与容器的ID相同,因此在本例中为“ 22”。如果以后使用此ID调用该函数,则只能访问所附的片段之一。 (我想这是最后一个,但是还没有检查。不过,似乎总是相同的。)
我没有快速浏览找到从FrameLayout中获得“活动”片段的方法,所以我想我将最后显示的Fragment的标签保存在某个地方。