6

我的问题

根据谷歌的文档:

您现在可以在片段中嵌入片段。这对于您希望将动态且可重用的 UI 组件放入本身是动态且可重用的 UI 组件的各种情况很有用。例如,如果您使用 ViewPager 创建 向左和向右滑动并占用大部分屏幕空间的片段,您 现在可以将片段插入到每个片段页面中。要嵌套片段,只需在要添加片段的片段上调用 ​​getChildFragmentManager()。这将返回一个 FragmentManager,您可以像通常从顶级活动中一样使用它来创建片段事务。例如,下面是一些从现有 Fragment 类中添加片段的代码:

Fragment videoFragment = new VideoPlayerFragment();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.video_fragment, videoFragment).commit();

所以我创建了我自己的PageFragment. 我的PageFragmentAdapter由 3 页组成PageFragment。我也有六个片段:Fragment1, Fragment2, Fragment3, FragmentA, FragmentB, FragmentC。在我的MainActivity我初始化了我的六个片段,我的ViewPager和它的PageFragmentAdapter(它为自己初始化了三个PageFragment)。

然后我使用这种方法将我的Fragment1, Fragment2,附加Fragment3到每个页面(每个PageFragmentPageFragmentAdapter

PageFragmentAdapter tPageFragmentAdapter = new PageFragmentAdapter(getSupportFragmentManager());
tPageFragmentAdapter.setFirstPage(tFragment1);
tPageFragmentAdapter.setSecondPage(tFragment2);
tPageFragmentAdapter.setThirdPage(tFragment3);

我可以接收(通过方法PageFragmentAdapter)片段并将“嵌套片段”放入我PageFragment的(当然是onCreate())中,例如:

getChildFragmentManager().beginTransaction()
.add(R.id.framelayout_history, mFragment)
.addToBackStack(null)
.commit();

注意:我PageFragment.setNestedFragment()用来设置mFragment它。

而且效果很好!它将帮助我(但这个故事不是关于它)简单地替换 ViewPager 中的片段,例如:

tPageFragmentAdapter.replaceFirstPage(tFragmentA);

但我有一个大问题。再次谷歌的文档:

PagerAdapter 的实现,它将每个页面表示为一个 Fragment,只要用户可以返回该页面,它就会永久保存在 Fragment 管理器中。此版本的分页器最适合在需要分页的情况下使用少数通常更静态的片段,例如一组选项卡。用户访问的每个页面的片段都 将保存在内存中,尽管它的视图层次结构 在不可见时可能会被破坏。这可能会导致使用大量内存,因为片段实例可以保持任意数量的状态。

如您所见PageFragmentAdapter,可以破坏每个我PageFragment的,当然还有它的嵌套片段。并且当它将被重新创建时,它将具有 NULL 而不是mFragment值。我正在尝试通过保存它getChildFragmentManager().putFragment(),然后通过getChildFragmentManager().getFragment(). 但它不起作用。

问题

所以我的问题是:如何将我的嵌套片段保存在我的父片段中?可能吗?

非常感谢您的帮助。亚历克斯。PS真的对不起我的英语:)

编辑

谢谢@AndroidBegin.com 的答案!

这似乎是新添加的对嵌套片段的支持中的一个错误。基本上,子 FragmentManager 在与活动分离时最终会出现内部状态损坏。为我修复它的短期解决方法是将以下内容添加到您调用 getChildFragmentManager() 的每个 Fragment 的 onDetach() 中:

@Override
public void onDetach() {
    super.onDetach();

    try {
        Field childFragmentManager = Fragment.class.getDeclaredField("mChildFragmentManager");
        childFragmentManager.setAccessible(true);
        childFragmentManager.set(this, null);

    } catch (NoSuchFieldException e) {
        throw new RuntimeException(e);
    } catch (IllegalAccessException e) {
        throw new RuntimeException(e);
    }
}
4

2 回答 2

11

在你的片段上试试这个。

public class Fragment2 extends SherlockFragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
            Bundle savedInstanceState) {
        View view = inflater.inflate(R.layout.viewpager_main, container, false);
        // Locate the ViewPager in viewpager_main.xml
        ViewPager mViewPager = (ViewPager) view.findViewById(R.id.viewPager);
        // Set the ViewPagerAdapter into ViewPager
        mViewPager.setAdapter(new ViewPagerAdapter(getChildFragmentManager()));
        return view;
    }

    @Override
    public void onDetach() {
        super.onDetach();
        try {
            Field childFragmentManager = Fragment.class
                    .getDeclaredField("mChildFragmentManager");
            childFragmentManager.setAccessible(true);
            childFragmentManager.set(this, null);
        } catch (NoSuchFieldException e) {
            throw new RuntimeException(e);
        } catch (IllegalAccessException e) {
            throw new RuntimeException(e);
        }
    }
}

来源:https ://www.swipetips.com/actionbarsherlock-side-menu-navigation-nested-viewpager-fragment-tabs-tutorial/

于 2013-09-24T15:50:37.433 回答
0

没有理由做任何概述的黑客行为。如果您正在使用 ViewPager 和 PagerAdapter(不确定它们在提问时是否存在),您可以使用 FragmentPagerAdapter 为您管理可滑动的标签片段。

class MyFragmentPagerAdapter(
  private val context: Context,
  fragmentManager: FragmentManager
) : FragmentPagerAdapter(fragmentManager) {
  override fun getCount() = 2

  override fun getItem(position: Int) = when(position) {
    0 -> FirstFragment()
    1 -> SecondFragment()
    else -> throw IllegalStateException("Unexpected position $position")
  }

  override fun getPageTitle(position: Int): CharSequence = when(position) {
    0 -> context.getString(R.string.first)
    1 -> context.getString(R.string.second)
    else -> throw IllegalStateException("Unexpected position $position")
  }
}

class ParentFragment: Fragment() {
  override fun onCreateView(...) = ...

  override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
    super.onViewCreated(view, savedInstanceState)
    viewPager.adapter = MyFragmentPagerAdapter(requireContext(), childFragmentManager)
    tabLayout.setupWithViewPager(viewPager)
  }
}
于 2019-11-24T13:04:08.090 回答