各位看官们大家好,上一回中咱们说的例子是"事件拦截之内部拦截",本章回介绍的例子是" 事件拦截之外部拦截"。闲话休提,言归正转,让我们一起Talk Android吧!
概念介绍
我们在上一章回中介绍了View中事件拦截的两种方法:内部拦截和外部拦截。程序中的画面都是由组件和布局组成的,组件又可以细分为View和ViewGroup。View通常位于ViewGroup中,如果在View中拦截事件就叫作内部拦截,如果在ViewGroup中拦截事件就叫作外部拦截。本章回中介绍外部拦截。
整体思路
在View的容器(通常是ViewGroup或者它的子类)中重写拦截事件的方法,并且不去调用父View的同类方法。常用的事件方法为onInterceptTouchEvent
()方法,我们可以在该方法中依据某种条件对事件进行拦截,拦截的方法就是返回true,并且不去调用父View的同类方法。这么做就是告诉父View以及它包含的子View:我已经处理了用户事件,你们不需要再处理用户事件了。这点和内部拦截的思路一样。
还一种思路是不让View的容器处理用户事件,而是让View自己去处理处理事件。这种思路的拦截方法返回false并且不去调用父View的同类方法。这么做就是告诉父View以及它包含的子View,我没有处理用户事件。你们处理吧。
正常情况下事件先经过View的容器,然后再传递给View,我们会在View容器中拦截事件,而不让容器中的View去处理用户事件.这个思路正好相反:不让View容器处理用户事件,而是让容器中的
View去处理事件,它有一个常用的场景:ViewPager
中包含List.滑动时ViewGoup会优先处理用户事件,进而导致ViewPager中的List无法响应用户事件。因此需要让ViewPager不去处理用户事件,把用户事件交给它包含的List处理。通俗点讲,这个思路就是开绿灯,就是说给某些事件放行。或者用计算机安全中的思路:添加白名单,对白名单内的事件不去处理。
示例代码
介绍完整体思路后,我们通过文字结合代码的方式来给大家做演示,第一种思路也就是在View的容器中拦截事件,该思路的实现方法和内部拦截事件的实现方法相同,我们不再演示,我们重点演示第二种思路的实现方法:View容器不去处理用户事件,而是让容器中的View处理用户事件。
public class CustomViewPager extends ViewPager {
public CustomViewPager(@NonNull Context context) {
super(context);
}
public CustomViewPager(@NonNull Context context, @Nullable AttributeSet attrs) {
super(context, attrs);
}
@Override
public boolean onInterceptTouchEvent(MotionEvent ev) {
boolean result = false;
if(ev.getRawY() > 711 && ev.getRawY() <1196) {
result = false;
if(ev.getAction() == MotionEvent.ACTION_MOVE) {
Log.d("EventView", "onInterceptTouchEvent: return");
return result;
}
}
super.onInterceptTouchEvent(ev);
return result;
}
}
在上面的代码中,我们自定义了一个类,该类继承自viewPage
,同时在类中重载onInterceptTouchEvent
()方法,该方法用来拦截用户事件,在该方法中我们判断某个区域的move事件就直接返回false不去处理用户事件,而是让ViewPage中的View去处理用户事件。这样ViewPager就不会滑动页面,还是让它里面的List去滑动,这样就能解决ViewPager和List滑动冲突的问题。
代码中使用数字表示事件的坐标,大家可以自行修改数值,来限制不同的区域,不过在实际项目中不建议这么做。
经验总结
外部拦截的优点是可以获取到子View区域内部和外部的事件,并且进行拦截;它还可能"开绿灯"不去拦截事件。缺点就是会对它里面的所有子View都有影响。如果想拦截view自身区域内的事件,推荐使用内部拦截;反之推荐使用外部拦截。
看官们,关于"事件拦截之外部拦截"的例子咱们就介绍到这里,欲知后面还有什么例子,且听下回分解!