写点什么

View 事件分发机制,看这一篇就够了,flutter 登录注册

用户头像
Android架构
关注
发布于: 刚刚

}}


return super.onInterceptTouchEvent(ev);}

内部解决法

从子 View 着手,父 View 先不要拦截任何事件,所有的事件传递给 子 View,如果子 View 需要此事件就消费掉,不需要此事件的话就交给 父 View 处理。


实现思路 如下,重写子 View 的 dispatchTouchEvent 方法,在 Action_down 动作中通过方法 requestDisallowInterceptTouchEvent(true) 先请求 父 View 不要拦截事件,这样保证子 View 能够接受到 Action_move 事件,再在 Action_move 动作中根据自己的逻辑是否要拦截事件,不需要拦截事件的话再交给 父 View 处理。


@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {int x = (int) ev.getRawX();int y = (int) ev.getRawY();int dealtX = 0;int dealtY = 0;


switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:dealtX = 0;dealtY = 0;// 保证子 View 能够接收到 Action_move 事件 getParent().requestDisallowInterceptTouchEvent(true);break;case MotionEvent.ACTION_MOVE:dealtX += Math.abs(x - lastX);dealtY += Math.abs(y - lastY);Log.i(TAG, "dealtX:=" + dealtX);Log.i(TAG, "dealtY:=" + dealtY);// 这里是够拦截的判断依据是左右滑动,读者可根据自己的逻辑进行是否拦截 if (dealtX >= dealtY) {getParent().requestDisallowInterceptTouchEvent(true);} else {getParent().requestDisallowInterceptTouchEvent(false);}lastX = x;lastY = y;break;case MotionEvent.ACTION_CANCEL:break;case MotionEvent.ACTION_UP:break;


}return super.dispatchTouchEvent(ev);}


更多细节,可以查看我的这篇文章,里面有详细介绍哦 ViewPager,ScrollView 嵌套ViewPager滑动冲突解决



View 双击,多击事件是怎么实现的

实现之前,我们首先来阐述一下思路,怎样实现双击事件,正所谓,授人以鱼不如授人以渔。


单击:用户点击一次之后,一段时间之内不再点击


双击;用户点击一次之后,一段时间之内再次点击


实现思路


  1. 我们监听 onTouch 事件,在 ACTION_DOWN 的时候,点击次数 clickCount +1;

  2. 同时,在 ACTION_DOWN 的时候,延时一段时间,执行相应的 Runnable 任务,这里我们用 handler 的 postDelayed 实现

  3. 在延时任务执行的时候,我们根据点击的次数,进行单击或者多级的回调,最后,记得重置点击次数,以及移除延时任务


open class MyDoubleTouchListener(private val myClickCallBack: MyClickCallBack) : OnTouchListener {


private var clickCount = 0 //记录连续点击次数 private val handler: Handler = Handler()


interface MyClickCallBack {fun oneClick() //点击一次的回调 fun doubleClick() //连续点击两次的回调}


override fun onTouch(v: View, event: MotionEvent): Boolean {if (event.action == MotionEvent.ACTION_DOWN) {clickCount++handler.postDelayed({if (clickCount == 1) {myClickCallBack.oneClick()} else if (clickCount == 2) {myClickCallBack.doubleClick()}handler.removeCallbacksAndMessages(null)//清空 handler 延时,并防内存泄漏 clickCount = 0 //计数清零}, timeout.toLong()) //延时 timeout 后执行 run 方法中的代码}return false //让点击事件继续传播,方便再给 View 添加其他事件监听}


companion object {private const val TAG = "MyClickListener"private val timeout = ViewConfiguration.getDoubleTapTimeout() //双击间四百毫秒延时


init {Log.i(TAG, "timeout is $timeout ")}}


}

三击事件

三级事件呢,其实也很简单,我们直接判断在指定时间间隔内点击的次数即可


open class MyMultiTouchListener(private val myClickCallBack: MyClickCallBack) : OnTouchListener {


private var clickCount = 0 //记录连续点击次数 private val handler: Handler = Handler()


interface MyClickCallBack {fun oneClick() //点击一次的回调 fun doubleClick() //连续点击两次的回调 fun threeClick() // 连续点击三次的回调}


override fun onTouch(v: View, event: MotionEvent): Boolean {if (event.action == MotionEvent.ACTION_DOWN) {clickCount++handler.postDelayed({if (clickCount == 1) {myClickCallBack.oneClick()} else if (clickCount == 2) {myClickCallBack.doubleClick()} else if (clickCount == 3) {myClickCallBack.threeClick()}handler.removeCallbacksAndMessages(null)//清空 handler 延时,并防内存泄漏 clickCount = 0 //计数清零}, timeout.toLong()) //延时 timeout 后执行 run 方法中的代码}return false //让点击事件继续传播,方便再给 View 添加其他事件监听}


companion object {private const val TAG = "MyClickListener"private val timeout = 600 //双击间四百毫秒延时


init {Log.i(TAG, "timeout is $timeout ")}}}



手势识别

在 Android 开发当中,几乎所有的事件都会与用户进行交互,而我们用得的最多的就是手势了。


我们知道当我们触摸屏幕的时候,会产生很多事件,比如 down,move,up, fling 事件等等。一些简单的处理,我们可以直接重写 View 的 onTouchEvent 方法,根据 View 的 MotionEvent 事件进行处理。


而 Google 为了方便开发者方便接入,提供了几个默认处理类,那就是 GestureDetector 和 ScaleGestureDetector。


GestureDetector 这个类对外提供了两个接口和一个外部类 。 接口:OnGestureListener,OnDoubleTapListener


内部类:SimpleOnGestureListener,同时实现了 OnGestureListener,OnDoubleTapListener 接口,如果只想使用接口里面的某个方法,可以直接使用它,方便快捷。


讲解之前,我们向来看一下怎么使用


GestureDetector(Context context, GestureDetector.OnGestureListener listener)

GestureDetector 基本使用

第一步,初始化 GestureDetector 对象


mDetector = GestureDetectorCompat(this, MyGestureListener())


可以看到有两个参数,第一个参数 context,第二个参数 OnGestureListener,我们可以直接实现 OnGestureListener 接口,也可以直接使用 GestureDetector.SimpleOnGestureListener


private class MyGestureListener : GestureDetector.OnGestureListener {


private val TAG = "GestureDemoActivity"


override fun onShowPress(e: MotionEvent?) {Log.d(TAG, "onShowPress: e is $e")}


override fun onSingleTapUp(e: MotionEvent?): Boolean {Log.d(TAG, "onSingleTapUp: e is $e")return false}


override fun onDown(event: MotionEvent): Boolean {Log.d(TAG, "onDown: $event")return true}


override fun onFling(event1: MotionEvent,event2: MotionEvent,velocityX: Float,velocityY: Float): Boolean {Log.d(TAG, "onFling: event2")return false}


override fun onScroll(e1: MotionEvent?, e2: MotionEvent?, distanceX: Float, distanceY: Float): Boolean {Log.d(TAG, "onScroll: distanceX is distanceY ")return false}


override fun onLongPress(e: MotionEvent?) {Log.d(TAG, "onLongPress: e is $e")}}


第二步:设置双击监


《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》
浏览器打开:qq.cn.hn/FTe 免费领取
复制代码



// 设置双击监听 mDetector.setOnDoubleTapListener(object : GestureDetector.OnDoubleTapListener {override fun onDoubleTap(e: MotionEvent?): Boolean {Log.d(TAG, "onDoubleTap: e is e")return false}


override fun onDoubleTapEvent(e: MotionEvent?): Boolean {Log.d(TAG, "onDoubleTapEvent: e is e")return false}


override fun onSingleTapConfirmed(e: MotionEvent?): Boolean {Log.d(TAG, "onSingleTapConfirmed: e is e")return false}


})


最后,重写 Activity 或者 View 的 onTouchEvent ,将事件交给 mDetector 处理。


通常会有两种写法,第一种是如果手势处理器处理了,直接返回 true,进行消费。否则,进行默认处理

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
View 事件分发机制,看这一篇就够了,flutter登录注册