Android中RecycleView与ViewPager冲突的解决方法及原理
1.概述
在实际开发中,我们经常遇到需要在ListView或RecycleView头部添加ViewPager实现Banner轮播效果,并需要添加下拉刷新,上拉加载功能。
但,横向滑动ViewPager时,稍微偏移就会失去焦点。
2.解决方案
我们知道事件拦截的顺序,父ViewGroup先接收到拦截,再传递给子ViewGroup或子View。事件的处理顺序是,子ViewGroup或子View先处理,若子ViewGroup处理了,父ViewGroup就不用处理,若子ViewGroup未处理,则传给父ViewGroup处理。
根据事件拦截原理,ViewPager和RecycleView相互冲突,RecycleView相当于父ViewGroup,ViewPager相当于子View,ViewPager和RecycleView相互冲突,将父View传到ViewPager里面处理,重写ViewPager。使用父类方法requestDisallowInterceptTouchEvent(true),用来子View告诉父容器不要拦截我们的事件的。
(1)重写ViewPager
importandroid.content.Context;
importandroid.support.v4.view.ViewPager;
importandroid.util.AttributeSet;
importandroid.view.MotionEvent;
importandroid.view.ViewGroup;
/**
*Developer:chunsofton2016/10/3116:04
*Email:chun_soft@qq.com
*Content:viewPager和RecycleView相互冲突,将父View传到ViewPager里面
*使用父类方法requestDisallowInterceptTouchEvent(true)
*用来子View告诉父容器不要拦截我们的事件的
*/
publicclassDecoratorViewPagerextendsViewPager{
privateViewGroupparent;
publicDecoratorViewPager(Contextcontext){
super(context);
}
publicDecoratorViewPager(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
publicvoidsetNestedpParent(ViewGroupparent){
this.parent=parent;
}
@Override
publicbooleandispatchTouchEvent(MotionEventev){
if(parent!=null){
parent.requestDisallowInterceptTouchEvent(true);
}
returnsuper.dispatchTouchEvent(ev);
}
@Override
publicbooleanonInterceptTouchEvent(MotionEventev){
if(parent!=null){
parent.requestDisallowInterceptTouchEvent(true);
}
returnsuper.onInterceptTouchEvent(ev);
}
@Override
publicbooleanonTouchEvent(MotionEventev){
if(parent!=null){
parent.requestDisallowInterceptTouchEvent(true);
}
returnsuper.onTouchEvent(ev);
}
}
(2)在Activity中:
DecoratorViewPagermPager=(DecoratorViewPager)mHeaderView.findViewById(R.id.viewpager); mPager.setNestedpParent((ViewGroup)mPager.getParent());
(3)在布局文件中:
处理ViewPager嵌套RecycleView卡顿问题
ViewPager里面添加了三个Fragment,Fragment里面添加了RecycleView,发现ViewPager左右滑动切换非常不流畅,存在滑动冲突,使用外部拦截进行处理soeasy~~~
/**
*Createdbymagicon2017/6/120012.外部拦截处理ViewPager嵌套RecycleView左右滑动切换Fragment卡顿问题
*/
publicclassMyViewPagerextendsViewPager{
floatx,y;
publicMyViewPager(Contextcontext){
super(context);
}
publicMyViewPager(Contextcontext,AttributeSetattrs){
super(context,attrs);
}
@Override
publicbooleanonInterceptHoverEvent(MotionEventevent){
switch(event.getAction()){
caseMotionEvent.ACTION_DOWN:
x=event.getX();
y=event.getY();
returnsuper.onInterceptHoverEvent(event);
caseMotionEvent.ACTION_MOVE:
if(Math.abs(x-event.getX())>Math.abs(y-event.getY()))
returntrue;
elsereturnfalse;
caseMotionEvent.ACTION_UP:
returnsuper.onInterceptHoverEvent(event);
}
returnsuper.onInterceptHoverEvent(event);
}
}
注意:ACTION_DOWN和ACTION_UP中不要直接返回false而要返回super.onInterceptHoverEvent(event),因为ViewGroup中对事件拦截方法做了些基本处理。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。