Android圖解淺析事件攔截機制

來源:互聯網
上載者:User

標籤:

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

當我們點擊一個按鈕時,通常會產生兩個或者三個事件---按下、滑動(可能無)、抬起。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");}@Overridepublic boolean onTouchEvent(MotionEvent event) {Log.e(Tag, "----->onTouchEvent");return super.onTouchEvent(event);}@Overridepublic 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");}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {Log.e(Tag, "----->dispatchTouchEvent");return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {Log.e(Tag, "----->onInterceptTouchEvent");return super.onInterceptTouchEvent(ev);}@Overridepublic 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輸出。


流程圖是這樣的:





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


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




Android圖解淺析事件攔截機制

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.