我们在项目中很多得时候会用到Activity+ViewPager+Fragment作为主框架,然后在其中一个Fragment中得列表中 添加一个Banner作为广告位,但是这样 容易有焦点冲突得问题
其实很关键地方在我们内部得那个BannerViewPager 这里需要对拦截器 进行编写
public class BannerViewPager extends ViewPager {
private float downX, downY;
public BannerViewPager(@NonNull Context context) {
super(context);
}
public BannerViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent e) {
boolean intercept = super.onInterceptTouchEvent(e);
switch (e.getAction()) {
case MotionEvent.ACTION_DOWN:
downX = e.getX();
downY = e.getY();
break;
case MotionEvent.ACTION_MOVE:
// 只要横向大于竖向,就拦截掉事件。
// 部分机型点击事件(slopx==slopy==0),会触发MOVE事件。
// 所以要加判断(slopX > 0 || sloy > 0)
float horizon=e.getX() - downX;
float slopX = Math.abs(e.getX() - downX);
float slopY = Math.abs(e.getY() - downY);
// Log.log("slopX=" + slopX + ", slopY=" + slopY);
if((slopX > 0 || slopY > 0) && slopX >= slopY){
int currentIndex=getCurrentItem();
int size=this.getAdapter().getCount();
if (currentIndex==0){
if (horizon>0){//向左滑动
requestDisallowInterceptTouchEvent(true);
intercept = true;
}
}
if (currentIndex==size-1){
if (horizon<0){//向右滑动
requestDisallowInterceptTouchEvent(true);
intercept = true;
}
}
}
break;
case MotionEvent.ACTION_UP:
intercept = false;
break;
}
return intercept;
}
}
因为事件传递的规则,如果我们需要拦截某个焦点 那么就要从写onInterceptTouchEvent方法
由于我们只是拦截其中某个条件下的事件,所以我们必须先调用super方法
boolean intercept = super.onInterceptTouchEvent(e);
如果我们想拦截某个事件,那么在onInterceptTouchEvent的返回值 必须位true
为了不影响父view不对我们处理进行拦截,所以调用
requestDisallowInterceptTouchEvent(true);
进行请求设置。
然后事件交给我们BannerViewPager进行处理
否则的话 事件就会一直传递下去。
我在代码里面设置了这样的逻辑:
int currentIndex=getCurrentItem();
int size=this.getAdapter().getCount();
if (currentIndex==0){
if (horizon>0){//向左滑动
requestDisallowInterceptTouchEvent(true);
intercept = true;
}
}
if (currentIndex==size-1){
if (horizon<0){//向右滑动
requestDisallowInterceptTouchEvent(true);
intercept = true;
}
}
这个是为了增加约束条件,在ViewPager第一个和最后一个页面的时候,不能再向两边滑动了,只能向内滑动。
还有一点需要注意,必须在BannerViewPager的适配器中的view添加点击事件
不然这个点击焦点 都没有view去消费掉,那么就会传递到最外层的ViewPager的onTouchEvent方法里面,那我们的拦截就没有意义了
参考的事件分发文章:https://www.jianshu.com/p/e99b5e8bd67b
这是我自己总结的事件分发的文章:https://blog.csdn.net/huazai30000/article/details/85316082