事件分发(一)
先自定义一个Imageview
package com.gode.myapplication.view
import android.content.Context
import android.util.AttributeSet
import android.util.Log
import android.view.MotionEvent
import androidx.appcompat.widget.AppCompatImageView
class ImageViewOnTouch(context: Context?, attrs: AttributeSet?) :
AppCompatImageView(context, attrs) {
override fun onTouchEvent(event: MotionEvent?): Boolean {
Log.e("msg","........ImageViewOnTouch.......onTouchEvent...");
return super.onTouchEvent(event)
}
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
Log.e("msg","........ImageViewOnTouch.......dispatchTouchEvent...");
return super.dispatchTouchEvent(event)
}
}
很简单里面就一个构造和两个方法,一个是是否分发,一个是处理动作:
继续接着走,在mainactivity里面也设置这连个方法:
package com.gode.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import android.util.Log
import android.view.MotionEvent
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
}
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
Log.e("msg","........main.......dispatchTouchEvent...");
return super.dispatchTouchEvent(ev)
}
override fun onTouchEvent(event: MotionEvent?): Boolean {
Log.e("msg","........main.......onTouchEvent...");
return super.onTouchEvent(event)
}
}
布局xml:
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<com.gode.myapplication.view.ImageViewOnTouch
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:background="@mipmap/ic_launcher"
tools:ignore="MissingConstraints" />
</androidx.constraintlayout.widget.ConstraintLayout>
里面就一个自定义布局,当点击空白处:
2020-07-03 14:23:42.091 15084-15084/com.gode.myapplication E/msg: ........main.......dispatchTouchEvent...
2020-07-03 14:23:42.092 15084-15084/com.gode.myapplication E/msg: ........main.......onTouchEvent...
2020-07-03 14:23:42.131 15084-15084/com.gode.myapplication E/msg: ........main.......dispatchTouchEvent...
2020-07-03 14:23:42.132 15084-15084/com.gode.myapplication E/msg: ........main.......onTouchEvent...
先执行的事件分发方法,这可能是 一个再简单不过了,继续接着改点击imageview了,看看会怎么执行:
2020-07-03 14:27:05.330 15084-15084/com.gode.myapplication E/msg: ........main.......dispatchTouchEvent...
2020-07-03 14:27:05.331 15084-15084/com.gode.myapplication E/msg: ........ImageViewOnTouch.......dispatchTouchEvent...
2020-07-03 14:27:05.331 15084-15084/com.gode.myapplication E/msg: ........ImageViewOnTouch.......onTouchEvent...
2020-07-03 14:27:05.331 15084-15084/com.gode.myapplication E/msg: ........main.......onTouchEvent...
2020-07-03 14:27:05.353 15084-15084/com.gode.myapplication E/msg: ........main.......dispatchTouchEvent...
2020-07-03 14:27:05.353 15084-15084/com.gode.myapplication E/msg: ........main.......onTouchEvent...
2020-07-03 14:27:05.354 15084-15084/com.gode.myapplication E/msg: ........main.......dispatchTouchEvent...
2020-07-03 14:27:05.354 15084-15084/com.gode.myapplication E/msg: ........main.......onTouchEvent...
先执行了mainactivity里面的 事件分发再走自定义imageview里面的事件分发,touch方法,最后回到了main的touch方法。
方法与上面同步:点击空白处,只是这里把ACTION_DOWN ACTION_MOVE ACTION_UP 加入进去 比如:
when (event?.action){
MotionEvent.ACTION_DOWN -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_DOWN...");
}
MotionEvent.ACTION_MOVE -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_MOVE...");
}
MotionEvent.ACTION_UP -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_UP...");
}
}
当点击空白处的时候:
2020-07-03 14:48:06.648 26995-26995/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 14:48:06.648 26995-26995/com.gode.myapplication E/msg: ........main....onTouchEvent...ACTION_DOWN...
2020-07-03 14:48:06.694 26995-26995/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_MOVE...
2020-07-03 14:48:06.694 26995-26995/com.gode.myapplication E/msg: ........main...onTouchEvent....ACTION_MOVE...
2020-07-03 14:48:06.695 26995-26995/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
2020-07-03 14:48:06.695 26995-26995/com.gode.myapplication E/msg: ........main..onTouchEvent.....ACTION_UP...
先执行的Down 从事件分发,再touch,不是把dispatchtouchevent方法执行完了才执行ontouchevent方法,而是先执行down再执行move这么的顺序来的
继续走,现在只操作activity的事件分发方法,在这里返回true就是拦截;
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
when (ev?.action){
MotionEvent.ACTION_DOWN -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_DOWN...")
}
MotionEvent.ACTION_MOVE -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_MOVE...")
}
MotionEvent.ACTION_UP -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_UP...")
}
}
return true
}
执行结果:
2020-07-03 14:59:38.135 3561-3561/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 14:59:38.173 3561-3561/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_MOVE...
2020-07-03 14:59:38.176 3561-3561/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
就是ontouchevent方法没有执行了,已经被消耗了。如果执行拦截down呢那么结果会怎样呢?
override fun dispatchTouchEvent(ev: MotionEvent?): Boolean {
when (ev?.action){
MotionEvent.ACTION_DOWN -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_DOWN...")
return true
}
MotionEvent.ACTION_MOVE -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_MOVE...")
}
MotionEvent.ACTION_UP -> {
Log.e("msg","........main...dispatchTouchEvent....ACTION_UP...")
}
}
return super.dispatchTouchEvent(ev)
}
2020-07-03 15:03:28.428 5155-5155/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:03:28.466 5155-5155/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_MOVE...
2020-07-03 15:03:28.466 5155-5155/com.gode.myapplication E/msg: ........main...onTouchEvent....ACTION_MOVE...
2020-07-03 15:03:28.468 5155-5155/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
2020-07-03 15:03:28.468 5155-5155/com.gode.myapplication E/msg: ........main..onTouchEvent.....ACTION_UP...
可以看出,这里只在down这里return true了,只有ontouchEvent 的down方法没有执行。其他move也是一样的。这里没有测试!!最后发现有个奇怪的问题,不管down方法里面是true还是false都是这样的结果。其他的move也是如此。
接下来是的,改自定义imageview了,在事件分发dispatchevent里面做处理:
override fun dispatchTouchEvent(event: MotionEvent?): Boolean {
when (event?.action){
MotionEvent.ACTION_DOWN -> {
Log.e("msg","........ImageViewOnTouch...dispatchTouchEvent....ACTION_DOWN...");
}
MotionEvent.ACTION_MOVE -> {
Log.e("msg","........ImageViewOnTouch....dispatchTouchEvent...ACTION_MOVE...");
}
MotionEvent.ACTION_UP -> {
Log.e("msg","........ImageViewOnTouch....dispatchTouchEvent...ACTION_UP...");
}
}
return true
}
2020-07-03 15:24:18.240 16961-16961/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:24:18.241 16961-16961/com.gode.myapplication E/msg: ........ImageViewOnTouch...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:24:18.254 16961-16961/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
2020-07-03 15:24:18.254 16961-16961/com.gode.myapplication E/msg: ........ImageViewOnTouch....dispatchTouchEvent...ACTION_UP...
看到这里心里其实有点底了,就是从顺序一步步来的,先从main里面执行事件分发DOWN没有拦截走自定义view的事件分发没有拦截,回到main里面执行UP的事件分发没有拦截走自定义的UP,这样一个顺序,这里在自定义的事件分发拦截,所以没有走ontouch方法,更加不会走main里面ontouch方法l。
继续在自定义view拦截ontouch方法:
override fun onTouchEvent(event: MotionEvent?): Boolean {
when (event?.action){
MotionEvent.ACTION_DOWN -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_DOWN...");
}
MotionEvent.ACTION_MOVE -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_MOVE...");
}
MotionEvent.ACTION_UP -> {
Log.e("msg","........ImageViewOnTouch...onTouchEvent....ACTION_UP...");
}
}
return true
}
2020-07-03 15:33:12.229 19679-19679/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:33:12.230 19679-19679/com.gode.myapplication E/msg: ........ImageViewOnTouch...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:33:12.230 19679-19679/com.gode.myapplication E/msg: ........ImageViewOnTouch...onTouchEvent....ACTION_DOWN...
2020-07-03 15:33:12.235 19679-19679/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
2020-07-03 15:33:12.235 19679-19679/com.gode.myapplication E/msg: ........ImageViewOnTouch....dispatchTouchEvent...ACTION_UP...
2020-07-03 15:33:12.235 19679-19679/com.gode.myapplication E/msg: ........ImageViewOnTouch...onTouchEvent....ACTION_UP...
这里可能会忘记刚开始是怎么的了,这里重新打印一下;(这里是什么都没有做拦截的)
2020-07-03 15:38:55.754 21208-21208/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:38:55.755 21208-21208/com.gode.myapplication E/msg: ........ImageViewOnTouch...dispatchTouchEvent....ACTION_DOWN...
2020-07-03 15:38:55.756 21208-21208/com.gode.myapplication E/msg: ........ImageViewOnTouch...onTouchEvent....ACTION_DOWN...
2020-07-03 15:38:55.756 21208-21208/com.gode.myapplication E/msg: ........main....onTouchEvent...ACTION_DOWN...
2020-07-03 15:38:55.784 21208-21208/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_MOVE...
2020-07-03 15:38:55.784 21208-21208/com.gode.myapplication E/msg: ........main...onTouchEvent....ACTION_MOVE...
2020-07-03 15:38:55.785 21208-21208/com.gode.myapplication E/msg: ........main...dispatchTouchEvent....ACTION_UP...
2020-07-03 15:38:55.785 21208-21208/com.gode.myapplication E/msg: ........main..onTouchEvent.....ACTION_UP...
是的你没看过与上面一样只是刚开始没有这么详细,这里没有走move和up!!!后期会补上。
本来自定义的ontouch方法是没有执行的,但这里return true了,表示拦截此方法走到了里面的方法,Down 和UP,但main里面的ontouch方法没有执行。好了,到这里差不多了。
总结:
执行顺序是走main里的事件分发Down 没有拦截走自定义的Down ->UP->ontouch (这里只走了自定义的ontouch 的DOWN)
哪里拦截,哪里就行自己的ontouch:
图有点丑!!
上一篇: 2019-10-17