最近想自己写一个日历组件,思路是使用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中是使用回调进行的数据更新,代码就不上了
这个问题已经困扰我两周了 求大佬指点