Android 如何制作ViewPager循环?

Android 如何制作ViewPager循环?,android,loops,android-fragments,Android,Loops,Android Fragments,我有一个带有一些视图的ViewPager。在右击最后一个之后,我想去第一个 我试过了 @Override public Fragment getItem(int arg0) { int i = arg0 % fragmentList.size(); return fragmentList.get(i); } @Override public int getCount() { return fragmentList.size()+1; } 但我犯了个错误 E/Andro

我有一个带有一些视图的ViewPager。在右击最后一个之后,我想去第一个

我试过了

@Override
public Fragment getItem(int arg0) {
    int i = arg0 % fragmentList.size();
    return fragmentList.get(i);
}

@Override
public int getCount() {
    return fragmentList.size()+1;
}
但我犯了个错误

E/AndroidRuntime(22912): java.lang.IllegalStateException: Fragment already added: RubricFragment{4136cd80 #1 id=0x7f06000c android:switcher:2131099660:0}

我会在ViewPager的末尾创建一个虚拟页面。 然后,当用户滚动到虚拟页面时,我使用此代码转到第一页。我知道这还远远不够完美

@Override
public void onPageScrolled(int position, float arg1, int arg2) {
    if (position >= NUM_PAGE-1) {
        mViewPager.setCurrentItem(0, true);
    }
}

一种可能性是设置如下屏幕:

C'A B C A'

C'看起来很像C,但当你滚动到那里时,它会将你切换到真正的C。 A'看起来就像A,但当你滚动到那里时,它会将你切换到真正的A

我会这样做:

请注意,这将调用的替代形式并传递
false
,以使跳转立即发生,而不是平滑滚动

我认为这有两个主要缺点。首先,当到达任意一端时,用户必须先让滚动停止,然后才能继续。第二,它意味着在第一页和最后一页中拥有所有视图的第二个副本。根据您的屏幕资源量的大小,这可能会排除此技术作为可能的解决方案

还要注意的是,由于视图寻呼机直到滚动结束后才允许点击进入底层控件,所以不为A'和C'片段设置clicklisteners等可能没问题


编辑:现在我自己实现了这一功能,还有一个相当大的缺点。当它从“A”切换到“A”或“C”切换到“C”时,屏幕会闪烁片刻,至少在我当前的测试设备上是这样。

这应该可以在没有虚拟页面的情况下完成工作:

private boolean isFirstOrLastPage;
private int currentPageIndex = 0;


@Override
public void onPageScrolled(int arg0, float arg1, int arg2) {
    if(currentPageIndex!=arg0){
        isFirstOrLastPage = false;
        return;
    }
    if((arg0==0 || arg0==PAGES.size()-1) && arg1 == 0 && arg2 == 0){
        if(isFirstOrLastPage){
                 //DO SOMETHING
        }else{
            isFirstOrLastPage = true;
        }
    }
}

@Override
public void onPageSelected(int arg0) {
    currentPageIndex = arg0;
}

这是可行的,可接受的答案不好,因为循环发生时存在滞后:

 @Override
public int getCount() {
    return Integer.MAX_VALUE;
}

@Override
public CharSequence getPageTitle(int position) {
    String title = mTitleList.get(position % mActualTitleListSize);
    return title;
}

@Override
public Object instantiateItem(ViewGroup container, int position) {
    int virtualPosition = position % mActualTitleListSize;
    return super.instantiateItem(container, virtualPosition);
}

@Override
public void destroyItem(ViewGroup container, int position, Object object) {
    int virtualPosition = position % mActualTitleListSize;
    super.destroyItem(container, virtualPosition, object);
}

答案如下:

我的解决方案基于benkc,但第一页和最后一页滚动动画被禁用,当页面“滚动”到真实页面时,滚动动画再次被启用,此方案可以解决第一个缺点

但是我的
ViewPager.setCurrentItem(position,false)
结果仍然有滚动动画,所以我实现的动画太快了,看不见

像这样的快速滚动动画,不要介意注释,只是我的代码没有使用以下方法:

public class FixedSpeedScroller extends Scroller {
    private int mDuration = 0;

    public FixedSpeedScroller(Context context) {
        super(context);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy, int duration) {
        super.startScroll(startX, startY, dx, dy, mDuration);
    }

    @Override
    public void startScroll(int startX, int startY, int dx, int dy) {
        super.startScroll(startX, startY, dx, dy, mDuration);
    }
}
并使用此方法查看寻呼机的活动

private Scroller scroller;
private void setViewPagerScroll(boolean instant) {
    try {
        Field mScroller = null;
        mScroller = ViewPager.class.getDeclaredField("mScroller");
        mScroller.setAccessible(true);
        if (scroller == null) {
            scroller = (Scroller) mScroller.get(mViewPager);
        }
        FixedSpeedScroller fss = new FixedSpeedScroller(mViewPager.getContext());
        mScroller.set(mViewPager, instant ? fss : scroller);

    } catch (NoSuchFieldException | IllegalArgumentException | IllegalAccessException e) {
        e.printStackTrace();
    }
}
和modify OnPageScrollStates更改如下,只有第一页或最后一页(我有5页)会将动画更改为快速滚动,否则会有正常滚动:

public void onPageScrollStateChanged(int state) {
    if (state == ViewPager.SCROLL_STATE_IDLE) {
        if (position == 0) {
            setViewPagerScroll(true);
            mViewPager.setCurrentItem(3);

        } else if (position == 4) {
            setViewPagerScroll(true);
            mViewPager.setCurrentItem(1);

        } else {
            setViewPagerScroll(false);
        }
    }
}

FixedSpeedScroller参考资料如下:

请检查此项嗨,你能找到一种避免闪烁的方法吗?这是我任务的神奇解决方案!这个解决方案有点慢。当快速滚动时,状态不会变为空闲状态,并且无法替换例如A'到A。在快速滚动(疯狂用户)停止后,代码可以完美地工作。这是不好的,因为循环发生时存在延迟,请查看我的答案以获得更好的解决方案!如果还有两个片段页面,那么当我用tablayout设置它时呢?我想让我的表格显示只有ABC片段,但这将使它显示5(C‘A’B C A’)。如果你这样做,是的,你可以实现无限滚动,但当滚动到最后一页时,你会看到类似返回scren1的动画。。
public void onPageScrollStateChanged(int state) {
    if (state == ViewPager.SCROLL_STATE_IDLE) {
        if (position == 0) {
            setViewPagerScroll(true);
            mViewPager.setCurrentItem(3);

        } else if (position == 4) {
            setViewPagerScroll(true);
            mViewPager.setCurrentItem(1);

        } else {
            setViewPagerScroll(false);
        }
    }
}