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中对事件拦截方法做了些基本处理。
总结
以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。