使用MotionEvent拖动图片

49 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 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轴坐标(相对于屏幕左顶点) |

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/ffd1171ae09f4facadd548df878b503e~tplv-k3u1fbpfcp-zoom-1.image)![](<> "点击并拖拽以移动")​编辑

​
​

### 小项目

先看效果图:

![](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/e60ff24e838648968d27910064aec48e~tplv-k3u1fbpfcp-zoom-1.image)![](<> "点击并拖拽以移动")

-   功能描述

            通过手指移动来拖动图片

           控制图片不能超过屏幕显示区域

-   技术点

         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 } }