1. 程式人生 > >Android圖解淺析事件攔截機制

Android圖解淺析事件攔截機制

當Android系統捕獲到使用者的各種輸入事件後,如何準確的傳遞給真正的需要這個事件的控制元件?Android提供了一整套完善的事件傳遞、處理機制,來幫助開發者完成準確的事件分配與處理,這裡我就不分析原始碼了,簡單點,圖形化分發過程,便於理解,待到後期分析dispatchTouchEvent原始碼時,回想這個圖解,會方便理解很多。

當我們點選一個按鈕時,通常會產生兩個或者三個事件---按下、滑動(可能無)、擡起。Android為觸控事件封裝了一個類----MotionEvent,其中假如我們重寫一個view的onTouchEvent事件中的引數就是一個MotionEvent。由於Android的View結構是樹形結構,也就是說,View可以放在ViewGroup裡面,通過不同的組合來實現不同的樣式。View可以放在一個ViewGroip,而這個ViewGroup又放在另一個ViewGroup裡面,甚至還有可能繼續巢狀。可能同一個事件,子View和ViewGroup都有可能想要進行處理,因此怎麼樣去“分發“和“攔截”的問題就產生了。

假設有這麼一個View,一個ViewGroupA,裡面嵌套了另一個ViewGroupB,而ViewGroupB裡面有一個view。整體的佈局結構如下:


佈局檔案如下:

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.viewdispatch.MainActivity" >

    <com.example.views.MyViewGroupA
        android:layout_width="260dp"
        android:layout_height="360dp"
        android:background="#f42c61" >

        <com.example.views.MyViewGroupB
            android:layout_width="200dp"
            android:layout_height="300dp"
            android:background="#042c61" >

            <com.example.views.MyView
                android:layout_width="160dp"
                android:layout_height="260dp"
                android:background="#cccccc" />
        </com.example.views.MyViewGroupB>
    </com.example.views.MyViewGroupA>

</RelativeLayout>

整體的Activity包含3個自定義的View,專案結構是MyView、MyViewGroupB、MyViewGroupA。所以整體Touch事件的主角是View和ViewGroup,而與View相關的Touch事件有2個dispatchTouchEvent和onTouchEvent;與ViewGroup相關的Touch事件有3個dispatchTouchEvent,onInterceptTouchEvent,onTouchEvent。所以我們在定義好View和ViewGroup後,讓其分別是實現這些方法。

程式碼如下:

MyView.java

import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;

public class MyView extends View {
	private String Tag = "MyView";

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

	public MyView(Context context, AttributeSet attrs) {
		super(context, attrs);
		Log.d(Tag, "----->MyView");
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		Log.e(Tag, "----->onTouchEvent");
		return super.onTouchEvent(event);
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent event) {
		Log.e(Tag, "----->dispatchTouchEvent");
		return super.dispatchTouchEvent(event);

	}

}
MyViewGroupA.java
import android.content.Context;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.ViewGroup;
import android.widget.LinearLayout;

public class MyViewGroupA extends LinearLayout {
	private String Tag = "MyViewGroupA";

	public MyViewGroupA(Context context, AttributeSet attrs, int defStyleAttr) {
		super(context, attrs, defStyleAttr);
		// TODO 自動生成的建構函式存根
	}

	public MyViewGroupA(Context context, AttributeSet attrs) {
		super(context, attrs);
		Log.d(Tag, "----->MyViewGroupA");
	}

	@Override
	public boolean dispatchTouchEvent(MotionEvent ev) {
		Log.e(Tag, "----->dispatchTouchEvent");
		return super.dispatchTouchEvent(ev);
	}

	@Override
	public boolean onInterceptTouchEvent(MotionEvent ev) {
		Log.e(Tag, "----->onInterceptTouchEvent");
		return super.onInterceptTouchEvent(ev);
	}

	@Override
	public boolean onTouchEvent(MotionEvent event) {
		Log.e(Tag, "----->onTouchEvent");
		return super.onTouchEvent(event);
	}

}
MyViewGroupB和A一樣,就不貼了。

其中上面事件的傳遞的返回值是這樣的,如果返回true,表示該View(ViewGroup)攔截了,不繼續往下分發事件了,如果返回false,表示不攔截,繼續往下分發。預設的呼叫父方法super.xxx是表示不攔截的意思。

下面就開始來驗證吧。

執行我們的專案,先看看我們3個view的載入情況吧:


可以看出是由外到內載入的。

好了,開始touch事件吧,現在我們先點選最外層粉紅的ViewGroupA,觀察Log輸出:


然後點選藍色區域的ViewGroupB,再觀察Log輸出:


最後點選MyView觀察輸出


由此,我們可以大致的繪製出如下圖所示的這樣的一個圖解流程。


現在假如我們修改MyViewGroupA中的onInterceptTouchEvent()事件,將其返回值改為True,點選任意一層view,現在我們再看log輸出:


可以看出只有A的3個事件進行了處理,由此事件被A攔截了。流程圖如下所示:


同理,將A的返回值改回來,我們修改MyViewGroupB的onInterceptTouchEvent()方法,也返回true,然後點選MyView或者MyViewGroupB,試試。Log輸出如下:


也就是事件只是分發到了MyViewGroupB,沒有到MyView,整個流程圖如下所示:


最後,假如底層的MyView想處理呢,相應的我們只用修改下onTouchEvent()的返回值就好,將其改為返回true.然後點選MyView看看log輸出。


流程圖是這樣的:


好了,文章到此結束,先簡單的對分發和攔截有個大致的瞭解,但事件分發機制還沒完全分析完,等待下一篇再來分析。

如果覺得分析的不過癮,可以繼續對此進行原始碼的分析,借用大神的分析部落格,結合本篇的圖解,相信本文應該還是有幫助的吧。喜歡的話,點個贊,留個言~

庖丁解牛,繼續分析:

http://blog.csdn.net/guolin_blog/article/details/9097463

http://blog.csdn.net/guolin_blog/article/details/9153747

最後,如果對文章有什麼疑惑,歡迎指出,共同進步!

相關推薦

Android圖解淺析事件攔截機制

當Android系統捕獲到使用者的各種輸入事件後,如何準確的傳遞給真正的需要這個事件的控制元件?Android提供了一整套完善的事件傳遞、處理機制,來幫助開發者完成準確的事件分配與處理,這裡我就不分析原始碼了,簡單點,圖形化分發過程,便於理解,待到後期分析dispatchT

Android:Touch事件攔截機制

道長說了這麼多自定義View,還沒說自定義View會遇到什麼問題,其實這個問題不止在自定義View中存在。在開發中遇到控制元件巢狀,堆疊都會出現,比如:點選子控制元件,子控制元件接收不到點選事件等等。這裡道長簡單說一下Android的事件攔截機制。重點是記錄一下

講講Android事件攔截機制

簡介 什麼是觸控事件?顧名思義,觸控事件就是捕獲觸控式螢幕幕後產生的事件。當點選一個按鈕時,通常會產生兩個或者三個事件——按鈕按下,這是事件一,如果滑動幾下,這是事件二,當手擡起,這是事件三。所以在Android中特意為觸控事件封裝了一個類MotionEvent,如果重寫onTouchEvent()方法,就會

詳細解析Android的View事件分發機制 附帶原始碼分析

前言 在Android中,事件分發機制是一塊很重要的知識點,掌握這個機制能幫你在平時的開發中解決掉很多的View事件衝突問題,這個問題也是面試中問的比較多的一個問題了,今天就來總結下這個知識點。 事件分發機制 事件分發原因 Android中頁面上的View是以

Android中View事件分發機制

View事件分發機制 今天要寫一寫Android中比較重要的一個核心,View事件分發機制。那麼事件分發機制是什麼,為什麼要寫這個呢, 下面將一一講解出來。 前言 相信大家對Android基礎知識都已經有所瞭解啦,因為畢竟Android已經涼了,應該也沒有多少新

Android點選事件傳遞機制詳解

在講正題之前我們講一段有關任務傳遞的小故事,拋磚迎玉下: 話說一家軟體公司,來一個任務,分派給了開發經理去完成: 開發經理拿到,看了一下,感覺好簡單,於是 開發經理:分派給了開發組長 開發組長:分派給了自己組員(程式設計師) 程式設計師:分派給了自己帶的實習生。

Android中的事件分發機制基本認識

一、基礎認識 Android 中事件的傳遞流程: Activity--------> Window(PhoneWindow)------>DecroView------->ViewGroup----->View; 二、Activity中事

Android ViewGroup 觸控事件傳遞機制

引言 上一篇部落格我們學習了Android View 觸控事件傳遞機制,不瞭解的同學可以檢視Android View 觸控事件傳遞機制。今天繼續學習Android觸控事件傳遞機制,這篇部落格將和大家一起探討ViewGroup的觸控事件傳遞機制。 示例

android進階4step4:Android實戰開發——事件分發機制

Android事件分發機制 為什麼需要事件分發機制? 比如:上圖 Button(View)的ViewGroup是FrameLayout2 FragmeLayout2的ViewGroup是FragmeLayout1 當點選Button時,所觸發的事件到底是交給誰來

android view觸控事件傳遞機制測試

沒有其它人為干預時: 詳細測試可以參考Github中的程式,地址: https://github.com/yifan42421/PhoneToPhoneScreen/tree/master/testmotionevent

android SDK-25事件分發機制--原始碼正確解析

android SDK-25事件分發機制–原始碼正確解析 Android 事件分發分為View和ViewGroup的事件分發,ViewGroup比View過一個攔截判斷,viewgroup可以攔截事件,從而決定要不要把事件傳遞給子view,因為view沒

Android View的事件分發機制筆記

涉及到的幾個概念: 同一個事件序列:手指接觸螢幕的那一刻起,到手指離開螢幕的那一刻結束。這個過程中產生的一系列事件,以down事件開始,中間可能包含多個move事件,最終以up事件結束。正

js 與 android 的互動(方法互呼叫) 和android向 js傳遞值, js向android傳引數 事件攔截看上一篇

mail_detail_v2.html <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewpor

理解Android View的事件傳遞機制

intercept andro eve cti android事件 分發 viewgroup event ont 在android事件傳遞一般包括三個對象: Activity,ViewGroup,View,事件分發順序為:Activity->ViewGroup->

原始碼分析:Android 的onTouch事件傳遞機制分析

當用戶觸控式螢幕幕的時候,最先接受到觸控事件的是Activity的dispatchTouchEvent(). 我們就從這裡開始分析事件的分發 Activity原始碼 看下Activity的dispatchTouchEvent()原始碼。

Android觸屏事件傳遞機制

首先,需要了解:View中有兩個方法:dispatchTouchEvent,onTouchEvent                 ViewGroup中有三個方法:dispatchTouchEvent,onTouchEvent,onInterceptTouchEvent                

android ViewGroup的事件分發機制

              android 事件分發機制的理解                Android 事件分發機制一直讓我很混亂,最近拼了,仔細研讀原始碼,有了一些自己的認識,今天記下.梳理下知識.    學習事件分發機制,就必須先了解一個物件. MontionEv

Android 事件分發機制 圖解

ack 理解 cnblogs png ont tor 自己的 block ans 在Android 開發中事件分發是比較重要的,也是比較難理解的,之前看過這方面的東西,以為自己弄懂了,也就沒太註意,最近面試呢,想著肯定要問到這一塊的東西,回顧的時候發現

圖解 Android 事件分發機制 和 handler 機制

在Android開發中,事件分發機制是一塊Android比較重要的知識體系,瞭解並熟悉整套的分發機制有助於更好的分析各種點選滑動失效問題,更好去擴充套件控制元件的事件功能和開發自定義控制元件,同時事件分發機制也是Android面試必問考點之一,如果你能把下面的一些事件分發圖當場畫出來肯定加分不少。廢

Android 觸控事件分發和攔截機制

Android 開發中,很多情況下,我們需要對觸控事件進行處理,但是當面對錯綜複雜的 Android 佈局時,我們如何準確的將一個使用者的觸控事件傳遞到對應的控制元件中並讓它進行處理呢? 首先,我們先假設這裡有這樣一個佈局: 我們可以很清楚的看到,一個很