从FragmentPagerAdapter动态添加和删除Fragments

5
我有一个FragmentPagerAdapter用于viewPager,初始时仅包含一个Fragment。我希望当用户从右向左滑动时动态地向适配器中添加新的Fragment,并在用户从左向右滑动时动态删除Fragment。我尝试使用此库https://github.com/commonsguy/cwac-pager但是该库中仅提供了通过按钮点击添加和删除fragment的选项。我尝试向viewpager添加OnPageChangeListener,但是回调方法(onPageScrolled和onPageScrollStateChanged)被调用的次数超过一次,这导致向FragmentPagerAdapter添加了多个fragment。请指导如何解决此问题。
3个回答

10

@dora: 我认为在你的情况下,FragmentStatePagerAdapter会对你有帮助。根据我的理解,我已经提到了它的使用方法。我希望这将帮助您做出决定。

实现ViewPager有两种方式: • FragmentStatePagerAdapter • FragmentPagerAdapter

FragmentStatePagerAdapter类消耗的内存较少,因为它在用户不可见时销毁片段,仅保留该片段的保存状态。

FragmentPagerAdapter: 在片段较少的情况下使用。但是对于大量片段的情况,使用AndroidFragmentPagerAdapter会导致卡顿和延迟的用户体验。

ViewPager可以容纳多少页面? 任何ViewPager将保持的条目数都由setOffscreenPageLimit()方法设置。离屏页面限制的默认值为3。这意味着ViewPager将跟踪当前可见的页面、左侧的一个页面和右侧的一个页面。跟踪页面的数量始终围绕当前可见的页面居中。

请按照此链接查看代码:http://www.truiton.com/2013/05/android-fragmentpageradapter-example/


6

我知道这篇文章已经老了,但我仍然会回答它,因为我曾经为此苦苦挣扎。

你需要使用FragmentStatePagerAdapter并覆盖getItemPosition()方法。创建一个你想要传递给碎片的东西列表,调用notifyDataSetChanged(),然后你就可以了!

这是适配器:

public class SectionsPagerAdapter extends FragmentStatePagerAdapter {

        List<String> mKeyList = new ArrayList<>();

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public int getItemPosition(Object object) {
            return POSITION_NONE;
        }

        @Override
        public Fragment getItem(int position) {
            // getItem is called to instantiate the fragment for the given page.
            // Return a PlaceholderFragment (defined as a static inner class below).
            return PlaceholderFragment.newInstance(mKeyList.get(position));
        }

        @Override
        public int getCount() {
            return mKeyList.size();
        }

        @Override
        public CharSequence getPageTitle(int position) {
            return "SCOUT " + (getCount() - position);
        }

        public void add(int position, String key) {
            mKeyList.add(position, key);
            notifyDataSetChanged();
        }
    }

这里是代码片段:

public static class PlaceholderFragment extends Fragment {

        private static final String ARG_SCOUT_KEY = "scout_key";

        public static PlaceholderFragment newInstance(String key) {

            PlaceholderFragment fragment = new PlaceholderFragment();
            Bundle args = new Bundle();
            args.putString(ARG_SCOUT_KEY, key);
            fragment.setArguments(args);
            return fragment;
        }

        @Override
        public View onCreateView(LayoutInflater inflater, ViewGroup container,
                                 Bundle savedInstanceState) {
            View rootView = inflater.inflate(R.layout.current_scout_fragment, container, false);

            //getArguments().getString(ARG_SCOUT_KEY));

            return rootView;
        }
    }

哦,天啊...谢谢,经过两天的努力终于找到了这个解决方案。非常棒。非常感谢。通过扩展FragmentStatePagerAdapter而不是FragmentPagerAdapter实现了目标。 - sandeepmaaram
添加很容易,现在问题是如何删除? - Rajesh N
它确实可以,而我已经转而使用自定义类(https://github.com/SUPERCILEX/Robot-Scouter/blob/4395fca46956b7b7a047c45e7ed9b3f6dcb809ff/app/src/main/java/com/supercilex/robotscouter/util/ui/MovableFragmentStatePagerAdapter.kt),该类支持移动项目。如果调用`notifyDataSetChanged()`,它只会根据需要添加或删除片段。这意味着每个片段都必须管理自己的更新,因为通知不会刷新片段。如果您使用类似Firebase或Room的东西,那么就没问题了。 - SUPERCILEX

2
当用户从右向左滑动时,我希望能动态地向适配器中添加一个新的Fragment;当用户从左向右滑动时,我希望能动态地移除一个Fragment。据我所知,任何PagerAdadpter都不支持这种操作,特别是ArrayPagerAdapter。页面需要存在,否则无法滑动到它。你不能先滑动,然后再添加页面。此外,我从未发现过你提出的模式有什么用例不能通过将页面放在适配器中但在滑动开始之前不填充(即你似乎试图避免的任何昂贵工作)来处理。

我正在尝试实现一个日历,使得用户向右滑动时可以进入下一周。但是在视图分页器的顶部还有一个按钮,允许用户切换月份。所以想象一下这种情况,假设用户首先使用月份切换按钮去到下个月(在切换月份的点击事件中,我写了viewpager.setCurrentItem(currentposition+1)),然后稍后决定滑动视图分页器以返回上一周。由于后退栈中只有一个片段,用户将无法返回到开始的日期。我的需求是:他应该回到他开始的地方。 - dora
@dora:“我正在尝试实现一个日历,这样每当用户从右向左滑动时,他就会进入下一周”-- ViewPager 不适合这个角色,因为未来有无限多的周,而过去则有很多周。 - CommonsWare
我不需要导航到过去,我只需要能够导航到当前时间和未来。所以请帮帮我,看是否有解决方法。 - dora
@dora:我还是不会使用ViewPager,而是会使用手势来实现其他的滑动效果。 - CommonsWare

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