事件分发(一)

    技术2023-07-25  83

    先自定义一个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:

     

    图有点丑!!

    Processed: 0.010, SQL: 10