weixin_43703944
Xzmpyy
2019-02-27 20:16
采纳率: 50%
浏览 845

如何解决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中是使用回调进行的数据更新,代码就不上了

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

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

2条回答 默认 最新

  • weixin_43703944
    Xzmpyy 2019-02-28 01:18
    已采纳

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

    点赞 评论
  • devmiao
    devmiao 2019-02-27 23:55
    点赞 评论

相关推荐