带有嵌套片段的ViewPager?

6

我的问题

根据Google的文档:

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

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

我创建了自己的PageFragment,我的PageFragmentAdapter包含3个页面的PageFragment。 我还有六个片段:Fragment1Fragment2Fragment3FragmentAFragmentBFragmentC。 在我的MainActivity中,我初始化了我的六个片段、我的ViewPager及其PageFragmentAdapter(它为自身初始化了三个PageFragment)。
然后,我使用这种方法将我的Fragment1Fragment2Fragment3附加到每个页面(每个PageFragment)的PageFragmentAdapter中:
PageFragmentAdapter tPageFragmentAdapter = new PageFragmentAdapter(getSupportFragmentManager());
tPageFragmentAdapter.setFirstPage(tFragment1);
tPageFragmentAdapter.setSecondPage(tFragment2);
tPageFragmentAdapter.setThirdPage(tFragment3);

我可以通过PageFragmentAdapter中的方法接收Fragment,并在我的PageFragment中创建“嵌套Fragment”(当然是在onCreate()中进行),例如:

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

注意:我使用PageFragment.setNestedFragment()来设置其中的mFragment

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

tPageFragmentAdapter.replaceFirstPage(tFragmentA);

但我有一个巨大的问题。再次谷歌文档:
PagerAdapter的实现,将每个页面表示为一个Fragment,并将其作为用户可以返回到该页面时在片段管理器中持久保存。当需要分页浏览一些通常比较静态的片段时,例如一组选项卡时,最好使用此版本的分页器。用户访问每个页面的片段将保留在内存中,尽管其视图层次结构可能在不可见时被销毁。这可能会导致使用大量内存,因为片段实例可以保持任意数量的状态。
如您所见,PageFragmentAdapter 可以销毁我的每个 PageFragment,当然也包括其中嵌套的片段。当它重新创建时,mFragment 值将为 NULL。我试图通过 getChildFragmentManager().putFragment() 来保存它,然后通过 getChildFragmentManager().getFragment() 来获取它。但是它没用。
问题
因此,我的问题是:如何在我的父片段中保存我的嵌套片段?这可能吗?
非常感谢您的帮助。Alex。P.S. 对于我的英语真的很抱歉:)
@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);
    }
}

帮帮我!分享你的想法! - AlexMomotov
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/


好的。如何从Field获取FragmentManager? - AlexMomotov
查看此问题以获取更多信息:https://dev59.com/Leo6XIcBkEYKwwoYORsV#15656428 - AndroidBegin.com
不要使用这个。 - EpicPandaForce

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)
  }
}

如果您使用了setupWithViewPager,则需要在onDestroy中调用viewPager上的clearOnPageChangeListeners - Daniel Gomez Rico

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接