如何解决ViewPager+Fragment+GridView实现无限滑动时页面切换的卡顿问题?

最近想自己写一个日历组件,思路是使用ViewPager+Fragment+GridView,如图

(https://img-ask.csdn.net/upload/201902/27/1551263494_687583.png)

最外层是一个DialogFragment

如果正常滑动,没有任何问题,但在快速滑动的时候,在滑到Fragment1和4时进行setCurrentItem时,会发生卡顿现象,即没有即时跳转导致已达到边界无法继续滑动的情况

慢滑

(https://img-ask.csdn.net/upload/201902/27/1551269528_523451.gif)

快滑

(https://img-ask.csdn.net/upload/201902/27/1551269556_845553.gif)

我自己尝试过的解决办法:
1. 一开始我以为是Fragment中布局过于复杂,导致在刷新数据时卡顿,但即时我去掉Fragment中的所有布局,仍会发生卡顿现象
2.后来我将问题定位在ViewPager的事件分发上,将ViewPager的自定义,将onInterceptTouchEvent方法复写直接返回true,现象消失,滑动无问题,但由于GridView中需要响应点击事件,所以我又做了事件拦截的判断,但无论怎么判断,只要不直接返回true,该现象就会发生

下面贴上我的部分代码:
1. 我在DialogFragment中为ViewPager绑定监听事件,在onPageScrollStateChanged中判断页面是否跳转,在页面滑到最左最右时进行跳转

//滑动状态监听

                override fun onPageScrollStateChanged(p0: Int) {
                    //1时表示正在滑动、2时表示滑动完毕、0时什么都没做,滑动时变化顺序为1>2>0
                    //在0时设置页面位置互换
                    if (p0 == 0){
                        position = calViewPager.currentItem
                        when (position) {
                            0 -> {
                                //到达最左侧Fragment时,刷新倒数第二个Fragment的数据与其保持一致,然后跳转,刷新部分代码省略
                                calViewPager.setCurrentItem(2, false)
                                //跳转完成后刷新其余页面,代码省略
                            }
                            3 -> {
                               //到达最右侧Fragment时,刷新第二个Fragment的数据与其保持一致,然后跳转,刷新部分代码省略
                                calViewPager.setCurrentItem(1, false)
                              //跳转完成后刷新其余页面,代码省略
                            }
                            2 -> {
                                //数据刷新,代码省略
                            }
                            1 -> {
                               //数据刷新,代码省略
                            }
                        }
                    }
                }

2.自定义了ViewPager,进行了事件拦截处理

private var xPosition:Float? = null
//    滑动点击判断、拦截
    override fun onInterceptTouchEvent(ev: MotionEvent?): Boolean {
        val res = super.onInterceptTouchEvent(ev)
        xPosition = if (ev!!.action == MotionEvent.ACTION_DOWN){
            ev.x
        }else{
            if (Math.abs(ev.x - xPosition!!) > 0){
                return true
            }else{
                ev.x
            }
        }
            return res
    }

3.ViewPager的Adapter

class MyCalendarViewPagerAdapter(fm: FragmentManager, private var fragmentsList:MutableList<Fragment>): FragmentPagerAdapter(fm){
    //Fragment个数
    override fun getCount(): Int {
        return fragmentsList.size
    }


    override fun getItem(p0: Int): Fragment {
        return fragmentsList[p0]
    }

    //不销毁Item
    override fun destroyItem(container: ViewGroup, position: Int, `object`: Any) {

    }

    override fun getItemPosition(`object`: Any): Int {
        return PagerAdapter.POSITION_NONE
    }

}

4.在Fragment中是使用回调进行的数据更新,代码就不上了

这个问题已经困扰我两周了 求大佬指点

weixin_43703944
Xzmpyy 这个问题我自己解决了,晚上灵光一闪想到,原因可能是滑动过快时,在Fragment1跳转前滑动事件落到了Fragment1上,于是我在ViewPager的onInterceptTouchEvent中,通过判断当前的item,如果为第一个或最后一个时,返回true,直接把touch事件拦截掉,这样即使快速滑动,也不会让一头一尾两个Fragment消费掉触摸事件
一年多之前 回复

2个回答

这个问题我自己解决了,晚上灵光一闪想到,原因可能是滑动过快时,在Fragment1跳转前滑动事件落到了Fragment1上,于是我在ViewPager的onInterceptTouchEvent中,通过判断当前的item,如果为第一个或最后一个时,返回true,直接把touch事件拦截掉,这样即使快速滑动,也不会让一头一尾两个Fragment消费掉触摸事件,这样改完后实测丝滑般流畅

weixin_43703944
Xzmpyy 这篇文章我看过了,并没有解决我的问题,如果不进行无限滑动只是单纯的从1滑到4从4滑到1是不卡的,我的问题是在滑到1时,为了实现无限滑动,我会让其跳转到3,这样永远可以往一个方向滑下去,但就在跳转的时候会出现卡顿
一年多之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问