问题说明:
当SwipeRefreshLayout中放置了VIEwPager控件,两者的滑动会相互冲突.具体表现为VIEwPager的左右滑动不顺畅,容易被SwipeRefreshLayout拦截(即出现刷新的VIEw).
问题原因:
VIEwPager本身是处理了滚动事件的冲突,它在横向滑动时会调用requestdisallowIntercepttouchEvent()方法使父控件不拦截当前的touch事件序列.但是SwipeRefreshLayout的requestdisallowIntercepttouchEvent()方法什么也没有做,所以仍然会拦截当前的touch事件序列.
问题分析:
为什么SwipeRefreshLayout的requestdisallowIntercepttouchEvent()方法什么都不做?
首先SwipeRefreshLayout继承自VIEwGroup.
在requestdisallowIntercepttouchEvent()方法什么都不做的情况下,用户可以从底部下拉刷新一次拉出LoadingVIEw.
如果方法调用VIEwGroup的requestdisallowIntercepttouchEvent()方法,可以解决VIEwPager的兼容问题,但是用户在界面底部下拉至头部后,无法继续下拉,需要手指放开一次才能拉出LoadingVIEw.
目标分析:
那么为了更加顺滑地滚动,想要的效果当然是一次性拉出LoadingVIEw.既然VIEwPager在左右滑动时才会调用requestdisallowIntercepttouchEvent()方法,那么SwipeRefreshLayout只应该在上下滑动时才拦截touch事件.
具体逻辑如下:
记录是否调用了requestdisallowIntercepttouchEvent()方法,并且设置为true.
在SwipeRefreshLayout中判断是否是上下滑动.
如果同时满足1,2,则调用super.requestdisallowIntercepttouchEvent(true).
否则调用super.requestdisallowIntercepttouchEvent(false).
注意:因为VIEwGroup的requestdisallowIntercepttouchEvent方法设置true后,touch事件在dispatchtouchEvent()方法中就会被拦截,所以需要在dispatchtouchEvent()方法中判断是否为上下滑动.
实现代码(部分):
//非法按键private static final int INVALID_POINTER = -1;//dispatch方法记录第一次按下的xprivate float mInitialdisPatchDownX;//dispatch方法记录第一次按下的yprivate float mInitialdisPatchDownY;//dispatch方法记录的手指private int mActivedispatchPointerID = INVALID_POINTER;//是否请求拦截private boolean hasRequestdisallowIntercept = false;@OverrIDepublic voID requestdisallowIntercepttouchEvent(boolean b) { hasRequestdisallowIntercept = b; // nope.}@OverrIDepublic boolean dispatchtouchEvent(MotionEvent ev) { switch (ev.getAction()) { case MotionEvent.ACTION_DOWN: mActivedispatchPointerID = MotionEventCompat.getPointerID(ev,0); final float initialDownX = getMotionEventX(ev,mActivedispatchPointerID); if (initialDownX != INVALID_POINTER) { mInitialdisPatchDownX = initialDownX; } final float initialDownY = getMotionEventY(ev,mActivedispatchPointerID); if (mInitialdisPatchDownY != INVALID_POINTER) { mInitialdisPatchDownY = initialDownY; } break; case MotionEvent.ACTION_MOVE: if (hasRequestdisallowIntercept) { //解决vIEwPager滑动冲突问题 final float x = getMotionEventX(ev,mActivedispatchPointerID); final float y = getMotionEventY(ev,mActivedispatchPointerID); if (mInitialdisPatchDownX != INVALID_POINTER && x != INVALID_POINTER && mInitialdisPatchDownY != INVALID_POINTER && y != INVALID_POINTER) { final float xDiff = Math.abs(x - mInitialdisPatchDownX); final float yDiff = Math.abs(y - mInitialdisPatchDownY); if (xDiff > mtouchSlop && xDiff * 0.7f > yDiff) { //横向滚动不需要拦截 super.requestdisallowIntercepttouchEvent(true); } else { super.requestdisallowIntercepttouchEvent(false); } } else { super.requestdisallowIntercepttouchEvent(false); } } break; case MotionEvent.ACTION_UP: case MotionEvent.ACTION_CANCEL: if (ev.getAction() == MotionEvent.ACTION_UP || ev.getAction() == MotionEvent.ACTION_CANCEL) { hasRequestdisallowIntercept = false; } break; } return super.dispatchtouchEvent(ev);}private float getMotionEventY(MotionEvent ev,int activePointerID) { final int index = MotionEventCompat.findPointerIndex(ev,activePointerID); if (index < 0) { return -1; } return MotionEventCompat.getY(ev,index);}private float getMotionEventX(MotionEvent ev,activePointerID); if (index < 0) { return -1; } return MotionEventCompat.getX(ev,index);}总结
以上是内存溢出为你收集整理的Android中ViewPager带来的滑动卡顿问题解决要点解析全部内容,希望文章能够帮你解决Android中ViewPager带来的滑动卡顿问题解决要点解析所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)