事件分發(一)

先自定義一個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:

 

圖有點醜!!

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章