开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第31天,点击查看活动详情
事件分发的三个重要方法:
1、dispatchTouchEvent()方法:会从Activity开始一层一层地向子View分发事件,直到没有子 View。(分发的时候,只能是View分发给子View,不能View分发给孙View)
2、onTouchEvent()方法:会在dispatchTouchEvent()方法调用到最底层View之后,再从最底 层View一层一层地往上回调,如果某个View的onTouchEvent方法返回true,那么就会停止 向上回调。
3、onInterceptTouchEvent方法:伴随着dispatchTouchEvent()方法存在,它的作用就是拦截 ViewGroup的事件,不让它继续向下分发事件。
Activity,View,ViewGroup和MotionEvent的主要方法:
Activity:
dispatchTouchEvent(ev: MotionEvent?): Boolean | 分发事件 |
onTouchEvent(ev: MotionEvent?): Boolean | 处理事件的回调 |
View:
dispatchTouchEvent(ev: MotionEvent?): Boolean | 分发事件 |
onTouchEvent(ev: MotionEvent?): Boolean | 处理事件的回调 |
setOnTouchListener(l:OnTouchListener) | 设置事件监听器 |
setOnClickListener(l:OnClickListener) | 设置点击监听 |
setOnLongClickListener(l:OnClickListener) | 设置长按监听 |
setOnCreateContextMenuListener(l:OnCreateContextMenuListener) | 用于创建菜单 |
注意:OnTouchListener中的onTouch()事件优先级高于onTouchEvent()事件,如果onTocuh()的返回结果为ture,那么该View的onTouchEvent()事件将不会被调用。
ViewGroup:
dispatchTouchEvent(ev: MotionEvent?): Boolean | 分发事件 |
``` | |
onInterceptTouchEvent(ev: MotionEvent?): Boolean |
注意:onInterceptTouchEvent方法只在ViewGroup中可以重写。
MotionEvent:
同时通过MotionEvent对象我们可以得到点击事件的x和y轴坐标。
系统提供的方法如下:
| | |
| --------- | --------------------- |
| getX() | 得到事件发生的x轴坐标(相对于当前视图) |
| getY() | 得到事件发生的y轴坐标(相对于当前视图) |
| getRawX() | 得到事件发生的x轴坐标(相对于屏幕左顶点) |
| getRawY() | 得到事件发生的y轴坐标(相对于屏幕左顶点) |
编辑
### 小项目
先看效果图:

- 功能描述
通过手指移动来拖动图片
控制图片不能超过屏幕显示区域
- 技术点
MotionEvent处理
对View进行动态定位(layout)
代码:
class MainActivity : AppCompatActivity(),View.OnTouchListener{ var lastX=0 var lastY=0 lateinit var imageView: ImageView lateinit var parentView:RelativeLayout var maxRight=0 var maxBottom=0 override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) imageView=findViewById(R.id.imageView4) parentView=imageView.parent as RelativeLayout imageView.setOnTouchListener(this) } override fun onTouch(p0: View?, event: MotionEvent): Boolean { val eventX=event.rawX val eventY=event.rawY when(event.action){ MotionEvent.ACTION_DOWN->{ if(maxRight==0){ maxRight=parentView.right maxBottom=parentView.bottom } lastX= eventX.toInt() lastY=eventY.toInt()} MotionEvent.ACTION_MOVE->{ var dx:Int=(eventX-lastX).toInt() var dy:Int=(eventY-lastY).toInt() var left=imageView.left+dx var top=imageView.top+dy var right=imageView.right+dx var bottom=imageView.bottom+dy //限制left>=0 if(left<0){ right+=-left left=0 } //限制top>=0 if(top<0){ bottom+=-top top=0 } //限制right<maxRight if(right>maxRight){ left-=right-maxRight right=maxRight } //限制bottom>=0 if(bottom>maxBottom){ top-=bottom-maxBottom bottom=maxBottom } imageView.layout(left, top, right, bottom) lastX=eventX.toInt() lastY=eventY.toInt() } } return true } }