美文网首页AndroidAndroid开发经验谈Android开发
【Android寻坑之路】ViewPager实现无限轮播切换页面

【Android寻坑之路】ViewPager实现无限轮播切换页面

作者: 紫豪 | 来源:发表于2017-08-25 14:56 被阅读2285次

    问题产生背景

    在使用ViewPager实现无限轮播效果时,为了达到无缝对接的效果,我在ViewPager的最左侧(position = 0)与左右侧(position = getCount() + 1)的位置新增了两个页卡用来对应映射尾页 / 首页的页卡图片,设计效果如下:


    banner.png

    设计好对应的映射item效果后,我在ViewPager的onPageScrolled(int position, float positionOffset, int positionOffsetPixels)方法中对ViewPager的滑动进行了监听并通过setCurrentItem(int item, boolean smoothScroll)方法进行首页 / 尾页切换从而达到无限轮播的效果,具体代码如下:

            /**
             * 页卡滚动状态回调
             * @param position 页卡位置 position=0,开始边界;position=getCount()-1,结束边界。
             * @param positionOffset 是当前页面滑动比例,如果页面向右翻动,这个值不断变大,
             *                       最后在趋近1的情况后突变为0。如果页面向左翻动,这个值不断变小,最后变为0
             * @param positionOffsetPixels 当前页面偏移的像素位置.
             */
            @Override
            public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) {
                if (isAutoLoop && positionOffset == 0) {// 允许无限轮播且滚动完成进入内部判断
                    if (position == 0) {// 如果position为0,则跳转至结束位置
                        // switch to the last page.
                        setCurrentItem(pagerAdapter.getRealPageEndPos(), false);
                    }
    
                    if (position == pagerAdapter.getCount() - 1) {// 如果position为pagerAdapter.getCount() - 1,则跳转至开始位置
                        // switch to the first page.
                        setCurrentItem(pagerAdapter.getRealPageStartPos(), false);
                    }
                }
            }
    

    这里我也对ViewPager切换过程中可能存在的问题进行了预防,参考【Android寻坑之路】解决ViewPager使用setCurrentItem跨距离(中间间隔多个page页)切换过渡动画闪现问题
    运行后发现出现了在最左侧 / 右侧滑动切换时出现了闪屏(白屏)的现象,具体如下图(实际问题比图片更突出,左右侧滑动都会闪屏):

    before.gif

    写在前面的解决方式

    在onPageScrollStateChanged(int state)方法中来进行轮播效果的控制

            @Override
            public void onPageScrollStateChanged(int state) {
                // 这里主要是解决在onPageScrolled出现的闪屏问题
                // (positionOffset为0的时候,并不一定是切换完成,所以动画还在执行,强制再次切换,就会闪屏)
                switch (state) {
                    case ViewPager.SCROLL_STATE_IDLE:// 空闲状态,没有任何滚动正在进行(表明完成滚动)
                        if (isAutoLoop) {
                            if (getCurrentItem() == 0) {
                                setCurrentItem(pagerAdapter.getRealPageEndPos(), false);
                            } else if (getCurrentItem() == pagerAdapter.getCount() - 1) {
                                setCurrentItem(pagerAdapter.getRealPageStartPos(), false);
                            }
                        }
                        break;
                    case ViewPager.SCROLL_STATE_DRAGGING:// 正在拖动page状态
                        break;
                    case ViewPager.SCROLL_STATE_SETTLING:// 手指已离开屏幕,自动完成剩余的动画效果
                        break;
                }
            }
    
    

    问题分析

    再次请出结构图:

    banner2.png

    这里我们先假设真实的C页面(position = 3)位C1,最左侧(position = 0)的黄色C页面为C2,,导致问题出现的步骤如下:
      在ViewPager的A页面(默认显示A页)右滑来切换至左侧的C2页(这个C2只是作为映射起到无缝对接的作用),当C2页切换出来后会快速在onPageScrolled方法中快速触发setCurrentItem方法跳转C1页。然而由于C2的动画未完成就开始切换至C1(这个是与onPageScrolled方法的调用时机有关),而切换至C1过程是无动画的,所以C2的动画还没彻底结束就直接切到了C1,由于滚动时机不对影响了无缝对接的效果造成了闪屏的现象(C2动画未完成,立即切换至C1,因为C2还在进行中而C1已经instantiateItem出来,那么C2页面就会被迅速回收,导致了闪屏的现象)。

    解决后的效果:

    after.gif

    关于OnPageChangeListener解析,请参考下文:
    ViewPager的addOnPageChangeListener方法详解


    如果您有更好的解决方案欢迎评论分享,如有错误,请批评指正,谢谢。

    相关文章

      网友评论

      • _那个人:ViewPager实现画廊模式的时候 这种方法是不可行的 还是可以明显的看到切换时的闪屏 gg
        MrWu_:@_那个人 你是怎么解决的?:smile:
        _那个人:@紫豪 我已解决
        紫豪:@_那个人 emm,问题场景不同,画廊模式又要另作处理了。

      本文标题:【Android寻坑之路】ViewPager实现无限轮播切换页面

      本文链接:https://www.haomeiwen.com/subject/etiudxtx.html