我正在开发具有以下UI结构的应用程序:
Activity
,名为 FoodActivity
Activity
实施bottom navigation。因此,可以显示三类食物:水果,肉和鱼 Activity
有一个很大的Fragment
容器,我在其中附加了水果的Fragment
,肉和当用户与底部标签交互时,。Fragment
( fish ,肉和鱼)都会在Fragments
之间显示导航:它可以显示水果列表,以及所选水果的细节。
Fragments
有另一个Fragment
容器,我将Fragments
附加到水果列表或水果详细信息中。 所以,它是一个主Activity
,它有一个很大的Fragment
容器,我交换Fragments
,然后嵌套其他Fragments
要使用标签从一个外部Fragment
切换到另一个外部{{从水果切换到肉),我在外部执行片段交易Fragment
容器:
private void switchFragment(Fragment fragment, String fragmentTag) {
final FragmentManager fm = getSupportFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_outer, fragment, fragmentTag);
ft.commit();
}
问题是切换第一级Fragments
时,ChildFragmentManager
的状态未保留。
例如,想象一下:
- 我从 FuitFragment 开始
- FruitFragment 在创建时附加嵌套的 FruitListFragment
- 用户在嵌套的Fragment
容器中导航,从 FruitListFragment 导航到 FruitDetailFragment
- 用户切换到另一个选项卡
- 用户切换回水果选项卡
- FuitFragment 的子FragmentManager *不会自动将 FruitDetailFragment 放入嵌套的片段容器中。
更具体地说,当切换回外部Fragment
时:
onCreate
,savedInstance
== null onCreateView
,savedInstance
== null 因此,当调用外部Fragment
onCreate
方法时,我无法判断是否附加了子Fragment
(通常与Activities
一样) 。
此外,如果我不附加它(使用实例变量检查我是否切换回它),子Fragment
容器将只是空的。
实验和笔记
我已经尝试过,如果我在附加它时将外部片段事务添加到backstack,当切换回它时,onCreate
方法不会被调用,而子FragmentManager
将记住并且附上之前的片段。
但是,根据Google's specifications on bottom navigation,我无法将其添加到backstack。
将setRetainInstace
设置为true不会产生任何影响。
那么,我应该怎么做才能正确恢复孩子的状态FragmentManager
?
我做错了什么,或者说Android中嵌套片段的所有内容都没有得到很好的支持(或者有点破碎)而且我不应该使用嵌套片段提供导航?
答案 0 :(得分:1)
正如阿巴斯指出的那样,问题在于我使用replace
来切换片段。
我已经更改为放置外部片段的Activity中的代码,并且它可以工作:
private void showChildFragment(int itemId) {
final FragmentManager fragmentManager = getSupportFragmentManager();
final FragmentTransaction transaction = fragmentManager.beginTransaction();
final Fragment currentFragment = getSupportFragmentManager().findFragmentById(R.id.fragment_outer);
if (currentFragment != null) {
Log.v(TAG, "Detaching item #" + currentFragment);
currentFragment.setMenuVisibility(false);
currentFragment.setUserVisibleHint(false);
transaction.detach(currentFragment);
}
// Do we already have this fragment?
final String tag = makeFragmentTag(container.getId(), itemId);
Fragment fragment = fragmentManager.findFragmentByTag(tag);
if (fragment == null) {
fragment = createFragmentForViewId(itemId);
Log.v(TAG, "Adding item #" + itemId + ": f=" + fragment);
transaction.add(container.getId(), fragment, tag);
} else {
Log.v(TAG, "Attaching item #" + itemId + ": f=" + fragment);
transaction.attach(fragment);
}
fragment.setMenuVisibility(true);
fragment.setUserVisibleHint(true);
transaction.commitAllowingStateLoss();
fragmentManager.executePendingTransactions();
}
private Fragment createFragmentForViewId(int itemId) {
switch (itemId) {
case FRAGMENT_ID_LIBRARY:
return LibraryNavigationFragment.createInstance();
case FRAGMENT_ID_FEED:
return WebAppFragment.createInstance("feed");
case FRAGMENT_ID_SUGGEST:
return WebAppFragment.createInstance("suggest");
default:
throw new IllegalArgumentException();
}
}
此代码几乎从android.support.v4.app.FragmentPagerAdapter
复制粘贴为ViewPagers
,使用Fragments工作,就像我想要的那样。
答案 1 :(得分:0)
使用getChildFragmentManager()不会崩溃。
private void switchFragment(Fragment fragment, String fragmentTag) {
final FragmentManager fm = getChildFragmentManager();
final FragmentTransaction ft = fm.beginTransaction();
ft.replace(R.id.fragment_outer, fragment, fragmentTag);
ft.commit();
}