Android事件分发机制四:学了事件分发有什么用?

“ ..... ”

前言

Android事件分发机制已经来到第四篇了,在前三篇中:

Android事件分发机制一:事件是如何到达activity的? : 从window机制出发分析了事件分发的整体流程,以及事件分发的真正起点

Android事件分发机制二:viewGroup与view对事件的处理 : 源码分析了viewGroup和view是如何分发事件的

Android事件分发机制三:事件分发工作流程 : 分析了触摸事件在控件树中的分发流程模型

那么关于事件分发的知识在上面三篇文章也就分析地差不多了,接下来就分析一下学了之后该如何使运用到实际开发中,简单阐述一下笔者的思考。

Android中的view一般由两个重要的部分组成:绘制和触摸反馈。如何精准地针对用户的操作给出正确的反馈,是我们学事件分发最重要的目标。

运用事件分发一般有两个场景:给view设置监听器和自定义view。接下来就针对这两方面展开分析,最后再给出笔者的一些思考与总结。

监听器

触摸事件监听器可以说是我们接触Android事件体系的第一步。监听器通常有:

OnClickListener : 单击事件监听器

OnLongClickListener : 长按事件监听器

OnTouchListener : 触摸事件监听器

这些是我们使用得最频繁的监听器,他们之间的关系是:

if (mOnTouchListener!=null && mTouchListener.onTouch(event)){ return true; }else{ if (单击事件){ mOnClickListener.onClick(view); }else if(长按事件){ mOnLongClickListener.onLongClick(view); } }

上面的伪代码可以很明显地发现:onTouchListener是直接把MotionEvent对象直接接管给自己处理且会最先调用,而其他的两个监听器是view判断点击类型之后再分别调用

除此之外,另一个很常见的监听器是双击监听器,但这种监听器并不是view默认支持的,需要我们自己去实现。双击监听器的实现思路可以参考view实现长按监听器的思路来实现:

当我们接收到点击事件时,可以发送一个单击延时任务。如果在延迟时间到还没收到另一个点击事件,那么这就是一个单击事件;如果在延迟时间内收到另一个点击事件,说明这是一个双击事件,并取消延时任务。

我们可以实现 view.OnClickListener 接口来完成以上逻辑,核心代码如下:

// 实现onClickListener接口 class MyClickListener() : View.OnClickListener{ private var isClicking = false private var singleClickListener : View.OnClickListener? = null private var doubleClickListener : View.OnClickListener? = null private var delayTime = 1000L private var clickCallBack : Runnable? = null private var handler : Handler = Handler(Looper.getMainLooper()) override fun onClick(v: View?) { // 创建一个单击延迟任务,延迟时间到了之后触发单击事件 clickCallBack = clickCallBack?: Runnable { singleClickListener?.onClick(v) isClicking = false } // 如果已经点击过一次,在延迟时间内再次接受到点击 // 意味着这是个双击事件 if (isClicking){ // 移除延迟任务,回调双击监听器 handler.removeCallbacks(clickCallBack!!) doubleClickListener?.onClick(v) isClicking = false }else{ // 第一次点击,发送延迟任务 isClicking = true handler.postDelayed(clickCallBack!!,delayTime) } } ... }

代码中实现了创建了一个 View.OnclickListener 接口实现类,并在类型实现单击和双击的逻辑判断。我们可以如下使用这个类:

val c = MyClickListener() // 设置单击监听事件 c.setSingleClickListener(View.OnClickListener { Log.d(TAG, "button: 单击事件") }) // 设置双击监听事件 c.setDoubleClickListener(View.OnClickListener { Log.d(TAG, "button: 双击事件") }) // 把监听器设置给按钮 button.setOnClickListener(c)

这样就实现了按钮的双击监听了。

其他类型的监听器如:三击、双击长按等等,都可以基于这种思路来实现监听器接口。

自定义view

在自定义view中,我们可以更加灵活地运用事件分发来解决实际的需求。举几个例子:

滑动嵌套问题:外层是viewPager,里层是recyclerView,要实现左右滑动切换viewPager,上下滑动recyclerView。这也就是著名的滑动冲突问题。类似的还有外层viewPager,里层也是可以左右滑动的recyclerView。
实时触摸反馈问题:如设计一个按钮,要让他按下的时候缩小降低高度,放开的时候恢复到原来的大小和高度,而且如果在一个可滑动的容器中,按下之后滑动不会触发点击事件而是把事件交给外层可滑动容器。

我们可以发现,基本上都是基于实际的开发需求来灵活运用事件分发。具体到代码实现,都是围绕着三个关键方法展开: dispatchTouchEvent 、 onIntercepterTouchEvent 、 onTouchEvent 。这三个方法在view和viewGroup中已经有了默认的实现,而我们需要基于默认实现来完成我们的需求。下面看看几种常见的场景如何实现。

实现方块按下缩小

我们先来看看具体的实现效果:

Android事件分发机制四:学了事件分发有什么用?

方块按下后,会缩小高度变低透明度增加,释放又会恢复。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/wssxwz.html