项目开发中,碰到这样一个情形:在点击页面空白处时会弹出状态栏,效果就如我上一篇博客一样。
那么何为空白处呢?
我的理解是:若是你这个点击事件没有其他View消费,那么便算是点击空白处了。
大致画一下页面布局:
那么在点击图中画框的其他地方,应该都能算上是空白处了,也就是在点击这些地方的时候,需要执行状态栏弹出的操作。
大致说一下页面布局的层次结构:
1 |
|
下面便来逐渐分析事件的分发。
清屏操作与RecyclerView的滑动冲突
需求中有向右滑动清屏
的操作,向左滑动的时候恢复。
我给整个布局parent_layout
设置了OnTouchListener,图中弹幕是使用的RecyclerView,RecyclerView本身就会处理滑动,那么就只能滑动RecyclerView之外的地方才能进行清屏。但是这样的体验不好,因为清屏必须要滑动空白地方,因为弹幕的原因可能导致空白地方很小。如何处理好与RecyclerView的滑动冲突呢?项目中,弹幕只具有上下滑动的功能,是不具备左右滑动的,所以事件分发给RecyclerView实际上是没有任何作用的,那么便可以在左右滑动的时候拦截掉事件,从而不分发给RecyclerView,拦截掉之后,若便会执行parent_layout
自身的OnTouchListener中的onTouch事件,在这个事件中做清屏的功能。
拦截横滑代码:
1 | @Override |
设置的OnTouchListener:
1 | class LiveGestureListener extends GestureDetector.SimpleOnGestureListener implements View.OnTouchListener { |
结合手势在onFling
中做了清屏与恢复的功能。
整个页面的空白处
布局层次中可以看到top_layout
是单独出来的,并且在FrameLayout的顶层。
详细说明一下:
1、清屏只清屏parent_layout
中的内容,top_layout
是不需要隐藏的,所以单独提了出来。
2、在顶层是为了提前消费事件,FrameLayout接到事件后会优先分发给顶层的孩子,即top_layout
,若top_layout
消费了,即点击了关闭或者主播信息等有消费事件的View,那么就不算是点击空白处
了,事件便不会分发给parent_layout
;若top_layout
没消费,即点击了空白处
,则会将事件分发给parent_layout
,parent_layout
便是我们自定义的FrameLayout,重写onTouchEvent,执行弹出状态栏的操作便可实现需求。
1 | @Override |
我们必须在ACTION_DOWN的时候返回true,才会继续收到ACTION_MOVE、ACTION_UP等事件,否则是收不到的。至于为什么,可以参考我之前的一篇博客Android事件分发机制学习小记。
我们再ACTION_UP的时候执行我们弹出状态栏的操作即可。
1 | holder.interactLayout.setListener(new HorizontalFrameLayout.DealClickEventListener() { |
最后上一下HorizontalFrameLayout
的完整代码:
1 | public class HorizontalFrameLayout extends FrameLayout { |
题外话
在我的另一篇博客一个关于Android滑动“因缺斯厅”的想法中说到一个点,顶部布局采用透明的,那么便会引发一个问题:需要透传关注
按钮的点击事件,因为透明布局是在顶部,会拦截掉点击事件,需要透传才能执行关注的响应事件。
1 | public class CustomRecyclerView extends RecyclerView { |
通过调用setView
设置需要透传的View,通过判断点击的位置是否在View的范围内,以及RecyclerView滑动的高度是否已经高过关注按钮的高度
,通过返回false,便可以将事件透传下去了。