Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> Android 事件分發機制

Android 事件分發機制

編輯:關於Android編程

View事件分發機制

什麼是分發?分發就是將一些事務交給下屬來處理,事件的分發其實包含了:事件的攔截,事件的處理(這樣說可能不是太准確)
事件攔截機制中,ViewGroup有onInterceptTouchEvent(),dispatchTouchEvent(),onTouchEvent()三個方法,分別起到事件分發、事件攔截、事件處理的作用
而View中只有dispatchTouchEvent(),onTouchEvent()方法。

假設有這樣一個Layout: ViewGroupA -> ViewGroupB -> View

當用戶點擊了這個布局的時候,
首先會從最外層ViewGroupA開始進行判斷,首先將事件分發給子View(dispatchTouchEvent()),即子View具有優先處理的權利

ViewGroupA代碼如下

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

/**
 * Created by feathers on 16-11-13.
 */

public class MyViewGroupA extends LinearLayout {

    private final String TAG = "MyViewGroupA";

    public MyViewGroupA(Context context) {
        super(context);
    }

    public MyViewGroupA(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroupA(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "dispatchTouchEvent()");
        boolean b = super.dispatchTouchEvent(ev);
        Log.i(TAG, "dispatchTouchEvent() return ");
        return b;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "onInterceptTouchEvent()");
        boolean b = super.onInterceptTouchEvent(ev);
        Log.i(TAG, "onInterceptTouchEvent() return");
        return b;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent()");
        boolean b = super.onTouchEvent(event);
        Log.i(TAG, "onTouchEvent() return");
        return b;
    }
}

ViewGroupB代碼同A類似:

import android.content.Context;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.LinearLayout;

/**
 * Created by feathers on 16-11-13.
 */

public class MyViewGroupB extends LinearLayout {

    private final String TAG = "MyViewGroupB";

    public MyViewGroupB(Context context) {
        super(context);
    }

    public MyViewGroupB(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyViewGroupB(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }
    @Override
    public boolean dispatchTouchEvent(MotionEvent ev) {
        Log.i(TAG, "dispatchTouchEvent()");
        boolean b = super.dispatchTouchEvent(ev);
        Log.i(TAG, "dispatchTouchEvent() return");
        return b;
    }

    @Override
    public boolean onInterceptTouchEvent(MotionEvent ev) {
        Log.i(TAG, "onInterceptTouchEvent()");
        boolean b = super.onInterceptTouchEvent(ev);
        Log.i(TAG, "onInterceptTouchEvent() return ");
        return b;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent()");
        boolean b = super.onTouchEvent(event);
        return b;
    }
}

地位最低的MyButton:

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.widget.Button;

/**
 * Created by feathers on 16-11-13.
 */

public class MyButton extends Button {

    private final String TAG = "MyButton";

    public MyButton(Context context) {
        super(context);
    }

    public MyButton(Context context, AttributeSet attrs) {
        super(context, attrs);
    }

    public MyButton(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
    }

    @Override
    public boolean dispatchTouchEvent(MotionEvent event) {
        Log.i(TAG, "dispatchTouchEvent()");
        boolean b = super.dispatchTouchEvent(event);
        Log.i(TAG, "dispatchTouchEvent() return");
        return b;
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        Log.i(TAG, "onTouchEvent()");
        boolean b = super.onTouchEvent(event);
        return b;
    }
}

xml如下:




   
       
           
       
   

點擊這個myButton:
輸出以下信息:

//**DOWN事件,手按下
//最高一級捕獲到動作,將事件分發給子View進行處理
// A開始分發
I/MyViewGroupA: dispatchTouchEvent()
// ViewGroupA是否要攔截事件,返回true代表攔截,則不會分發給子view
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
// 如果沒有被A攔截,B則會接受到此事件,然後同A相同,分發給子view,看看它們要不要處理
// B開始分發
I/MyViewGroupB: dispatchTouchEvent()
// ViewGroupB是否要攔截這個事件
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return 
// 沒有被攔截,則讓MyButton獲取事件,同樣先進性事件分發
I/MyButton: dispatchTouchEvent()
// 因為沒有子View,所以不需要onIntercepTouchEvent()取判斷是否交給子View處理
// 直接調用onTouchEvent()處理事件,但是有時候子View不想處理,如果不想處理,則onTouchEvent()可以返回false
I/MyButton: onTouchEvent()
// MyButton處理結束後,代表B的事件分發結束
I/MyButton: dispatchTouchEvent() return
// MyButton結束後,B也結束了
I/MyViewGroupB: dispatchTouchEvent() return
// 最後ViewGroupA的事件分發同樣也結束了
I/MyViewGroupA: dispatchTouchEvent() return 
//**UP事件,手抬起
I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return 
I/MyButton: dispatchTouchEvent()
I/MyButton: onTouchEvent()
I/MyButton: dispatchTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent() return
I/MyViewGroupA: dispatchTouchEvent() return 

當我們將事件攔截在ViewGroupB中會出現什麼情況呢?
將ViewGroupB的onInterceptTouchEvent()返回值改為true

再來看log:

// GroupA給子View分發事件
I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
// GroupB給子View分發事件
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent()
I/MyViewGroupB: onInterceptTouchEvent() return 
// 這裡發現onInterceptTouchEvent()的返回值為true,即需要攔截事件,此時ViewGroupB發現事件被攔截了,那麼它自己就會處理事件
I/MyViewGroupB: onTouchEvent() // 調用onTouchEvent()處理事件
// B分發完成
I/MyViewGroupB: dispatchTouchEvent() return
// B分發完成後發現 A又調用了onTouchEvent()處理了事件,這是因為onTouchEvent()返回了false,即B雖然根據事件進行了處理,但是並沒有消耗掉事件,這稱為事件回傳。
// 前面的MyButton處理事件後B沒有調用onTouchEvent()的原因在於MyButton將事件消耗掉了,所以可以理解為事件被吃掉了,沒有事件可以回傳。
I/MyViewGroupA: onTouchEvent()
I/MyViewGroupA: onTouchEvent() return
// A分發完成
I/MyViewGroupA: dispatchTouchEvent() return 

既然dispatchTouchEvent()決定權這麼大,那我們將dispatchTouchEvent()置為false會不會就代表這個事件不被處理了呢?
把ViewGroupView的dispatchTouchEvent()置為false:
LOg如下:

I/MyViewGroupA: dispatchTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent()
I/MyViewGroupA: onInterceptTouchEvent() return
I/MyViewGroupB: dispatchTouchEvent()
I/MyViewGroupB: dispatchTouchEvent() return
// A發現B理都不理它,直接自己處理了
I/MyViewGroupA: onTouchEvent()
I/MyViewGroupA: onTouchEvent() return
I/MyViewGroupA: dispatchTouchEvent() return
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved