【问题标题】:ViewPager with Nested Fragments?带有嵌套片段的 ViewPager?
【发布时间】:2013-09-24 09:37:04
【问题描述】:

我的问题

根据 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附加到PageFragmentAdapter的每个页面(每个PageFragment):

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

但我有一个大问题。 同样是 Google 的文档:

PagerAdapter 的实现,将每个页面表示为一个 Fragment 只要用户一直保存在片段管理器中 可以返回页面。此版本的寻呼机最适合在以下情况下使用 有一些通常更静态的片段需要分页 通过,例如一组选项卡。 用户每个页面的片段 访问将保存在内存中,尽管其视图层次结构可能 在不可见时销毁。这可能会导致使用显着的 内存量,因为片段实例可以保持任意 状态量。

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

问题

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

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

编辑

谢谢@AndroidBegin.com 的答案!

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

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

【问题讨论】:

  • 帮帮我!分享你的想法!

标签: android android-fragments nested android-viewpager fragmentpageradapter


【解决方案1】:

在你的片段上试试这个。

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/

【讨论】:

【解决方案2】:

没有理由做任何概述的黑客行为。如果您使用 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,您需要在viewPager 上拨打clearOnPageChangeListeners onDestroy
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-09-14
  • 1970-01-01
  • 2014-01-17
  • 1970-01-01
  • 2013-11-17
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多