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里面处理,重写View Pager。使用父类方法requestDisallowInterceptTouchEvent(true)
,用来子View告诉父容器不要拦截我们的事件的。
- (1)重写ViewPager
import android.content.Context;
import android.support.v4.view.ViewPager;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.ViewGroup;
/**
* Developer:chunsoft on 2016/10/31 16:04
* Email:chun_soft@qq.com
* Content:viewPager和RecycleView相互冲突,将父View传到ViewPager里面
* 使用父类方法requestDisallowInterceptTouchEvent(true)
* 用来子View告诉父容器不要拦截我们的事件的
*/
public class DecoratorViewPager extends ViewPager{
private ViewGroup parent;
public DecoratorViewPager(Context context) {
super(context);
}
public DecoratorViewPager(Context context, AttributeSet attrs) {
super(context, attrs);
}
public void setNestedpParent(ViewGroup parent) {
this.parent = parent;
}
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (parent != null){
parent.requestDisallowInterceptTouchEvent(true);
}
return super.dispatchTouchEvent(ev);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
if (parent != null){
parent.requestDisallowInterceptTouchEvent(true);
}
return super.onInterceptTouchEvent(ev);
}
@Override
public boolean onTouchEvent(MotionEvent ev) {
if (parent != null){
parent.requestDisallowInterceptTouchEvent(true);
}
return super.onTouchEvent(ev);
}
}
- (2)在Activity中:
DecoratorViewPager mPager = (DecoratorViewPager) mHeaderView.findViewById(R.id.viewpager);
mPager.setNestedpParent((ViewGroup) mPager.getParent());
- (3)在布局文件中:
<com.chunsoft.baseframework.utils.view.DecoratorViewPager
android:id="@+id/viewpager"
android:layout_width="match_parent"
android:layout_height="180dp" />