无限滚动的ViewPager

19

看起来似乎是可能的,但我有点难以想出如何实现一个可以无限翻页的 ViewPager

我的使用情况是用于显示每月一次的日历,并且可以通过翻页足够多次来切换到任何一个月份。

目前我只是 扩展 PagerAdapter,并添加了3个自定义的 MonthViews

    @Override
    public Object instantiateItem(View collection, int position) {
        final MonthView mv = new MonthView(HistoryMonthActivity.this);
        mv.setLayoutParams(new ViewSwitcher.LayoutParams(
                android.view.ViewGroup.LayoutParams.MATCH_PARENT,
                android.view.ViewGroup.LayoutParams.MATCH_PARENT));
        mv.setSelectedTime(mTime);

        ((DirectionalViewPager) collection).addView(mv, 0);

        return mv;
    }
我希望一次只保留3个MonthView在内存中,这样当用户切换时就不会有巨大的延迟来显示来自我的数据库的每一个MonthView的数据。因此,每当显示一个新页面时,我需要删除一个MonthView并添加一个MonthView。如果有更好的实现同样功能的方法,我很乐意听取!我正在考虑尝试使用FragmentStatePagerAdapter
2个回答

8

我能够使用我的MonthView,我的PagerAdapterOnPageChangeListener,以及编辑ViewPager源代码来实现这一点。如果有人对我是如何实现的感兴趣,请查看源代码或在评论中提出具体问题。


你为让它正常工作付出了很多努力!你可以利用 PagerAdapter 方法 getItemPosition() 来简化它。 - ohhorob
1
也许吧,但从文档来看,这需要调用notifyDataSetChanged(),而根据我的经验,这种方法并不是非常高效,会导致明显的图形卡顿和屏幕闪烁。 - Jon Willis
@JonWillis notifyDataSetChanged() 不应该引起问题。我建议再试一次以确保。 - StackOverflowed
请注意,我必须添加这行代码以防止应用程序在需要对所有页面进行常量访问时崩溃:mViewPager.setOffscreenPageLimit(3); - Oleg Vaskevich
你能分享一下你对ViewPager所做的更改吗? - Leandros
很棒的艺术品! - Salman Khakwani

6

实际上,我一直在研究各种实现“无限”分页的方法,尽管人们认为时间是无限的(即使我们有时间的开始和结束的概念),但计算机处理的是离散的。存在最小和最大时间(可以随着时间推移进行调整,记得Y2K恐慌的基础吗?)。

无论如何,本次讨论的重点是通过实际有限的时间范围支持相对无限的日期范围应该是/是足够的。一个很好的例子是Android框架的CalendarView实现及其中的WeeksAdapter。默认的最小日期是1900年,而默认的最大日期是2100年,这应该轻松覆盖今天10年半径内任何人99%的日历使用情况。

他们在周的实现中所做的(计算最小和最大日期之间的周数)成为pager中页面的数量。记住,pager不需要同时维护所有这些页面 (setOffscreenPageLimit(int)),它只需要能够根据页面编号(或索引/位置)创建页面。在这种情况下,索引是该周距离最小日期的周数。采用这种方法,您只需要维护最小日期和页面数量(到最大日期的距离),然后对于任何页面,您都可以轻松计算与该页面相关联的周。无需绕过ViewPager不支持循环(即无限分页)的事实,并试图强制其像可以无限滚动一样运行。

new FragmentStatePagerAdapter(getFragmentManager()) {
    @Override
    public Fragment getItem(int index) {
        final Bundle arguments = new Bundle(getArguments());
        final Calendar temp_calendar = Calendar.getInstance();
        temp_calendar.setTimeInMillis(_minimum_date.getTimeInMillis());
        temp_calendar.setFirstDayOfWeek(_calendar.getStartOfWeek());
        temp_calendar.add(Calendar.WEEK_OF_YEAR, index);
        // Moves to the first day of this week
        temp_calendar.add(Calendar.DAY_OF_YEAR,
                -UiUtils.modulus(temp_calendar.get(Calendar.DAY_OF_WEEK) - temp_calendar.getFirstDayOfWeek(),
                7));
        arguments.putLong(KEY_DATE, temp_calendar.getTimeInMillis());
        return Fragment.instantiate(getActivity(), WeekDaysFragment.class.getName(), arguments);
    }

    @Override
    public int getCount() {
        return _total_number_of_weeks;
    }
};

然后WeekDaysFragment可以轻松显示从传递给它的参数日期开始的一周。

1
很好的超越常规思维方式。 - aluxian
我知道这是一个旧答案,但为了增加更多的力量,我刚刚测试了Google日历应用程序,我能够回溯到1969年12月。我能够一直前进到2037年1月。因此,在实现日历时,没有必要过度强调这一点,即使您需要回溯几千年。 - Not Gabriel

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