欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

事件分发(一)

程序员文章站 2022-05-14 15:26:45
...

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

事件分发(一)

 

图有点丑!!

相关标签: 事件分发