Android Honeycomb:如何更改 FrameLayout 中的 Fragments,而不重新创建它们? [英] Android Honeycomb: How to change Fragments in a FrameLayout, without re-creating them?

查看:22
本文介绍了Android Honeycomb:如何更改 FrameLayout 中的 Fragments,而不重新创建它们?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以在不一直重新创建 Fragment 的情况下在 Fragment 之间切换?如果是,怎么办?

is it possible to switch between Fragments without re-creating them all the time? If so, how?

在文档中我找到了一个例子来替换 Fragments.

In the documentation I found an example of how to replace Fragments.

// 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();

但我不想每次需要它们时都从头开始创建片段.

But I don't want to create my Fragments from the scratch every time I need them.

我还发现了这个隐藏/显示片段的例子:

// 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 的片段?

But how would I create a fragment with an ID outside an XML file?

我认为这可能与这个问题有关,但没有不是答案.:/

I think this might be related to this question, but there isn't an answer. :/

非常感谢您,水母

我现在就是这样做的:

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();

如果我调用设置,然后调用其他内容,然后返回设置,toast 首先给我null",然后给我Settings:SettingsFragment{40ef...".

If I call up the settings, then something else, and then go back to settings, the toast gives me "null" first and "Settings:SettingsFragment{40ef..." second.

但是,如果我将 fragmentTransaction.add(R.id.framelayout_content, set, SET); 替换为 fragmentTransaction.replace(R.id.framelayout_content, set, SET); 我不断收到null"、null"、null"...所以它似乎没有按标签找到 Fragment.

However, if I replace fragmentTransaction.add(R.id.framelayout_content, set, SET); with fragmentTransaction.replace(R.id.framelayout_content, set, SET); I keep getting "null", "null", "null"... so it doesn't seem to find the Fragment by tag.

编辑 2:

添加 fragmentTransaction.addToBackStack(null); 做到了.:)这节省了整个隐藏/记住显示哪个片段的过程,所以我认为这是最优雅的解决方案.

Adding fragmentTransaction.addToBackStack(null); did the trick. :) This saves the whole hiding/memorizing which fragment is shown part so I suppose it's the most elegant solution for this.

我发现教程对该主题非常有帮助.

I found this tutorial quite helpful on the topic.

编辑 3:

看着我的代码,我意识到我可以去掉一些部分,所以我把它改成了:

Looking at my code I realized I could get rid of some parts, so I changed it to:

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, SET);
fragmentTransaction.addToBackStack(null);
fragmentTransaction.commit();

然而,这调用了 IllegalStateException: Fragment already added,与 这里.有没有简单的方法来防止这种情况?否则我想我可能会切换回隐藏/显示位.

However, this invoked an IllegalStateException: Fragment already added, much the same like here. Is there an easy way to prevent this? Otherwise I think I might switch back to the hide/show bit.

推荐答案

这可能取决于您试图避免重新创建的内容.

It could depend on what you are trying to avoid being re-created.

// 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 中的要求更新任何内部状态.

In your example example when you hit the back button from your newFragment the previous fragment will be shown (you'll get an onCreateView, onActivityCreated but no onCreate) so that fragment isn't being re-created as such. As for you newFragment you can still keep it around if you plan to use it again updating any internal state as required in say onCreate or onActivityCreated.

如果您只是有一个菜单列表,其中每个条目都在右侧窗格中调用不同的片段,那么添加到后台堆栈不是您想要的.为此,您可以预先在每个片段上调用 ​​add(...) 并根据需要简单地隐藏/显示每个片段(我没有测试过).否则我建议保留对每个片段的引用,在选择不同的菜单项时调用 replace(...) 以确保您不会添加到返回堆栈中.

If you simply have a menu list with each entry invoking a different fragment in a right pane then adding to the back stack is not what you want. For this you might get away with calling add(...) on each fragment up-front and simply hide/show each fragment as required (I've not tested this). Otherwise I would suggest holding a reference to each fragment, call replace(...) on selecting a different menu item ensuring that you don't add to the back stack.

这篇关于Android Honeycomb:如何更改 FrameLayout 中的 Fragments,而不重新创建它们?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆