Android 事件分發

來源:互聯網
上載者:User

標籤:android   事件分發   

當你作為一名應屆生去面試的時候,面試官可能就是簡單的問你Android的四大組件,各種布局等基礎知識,但你作為一名有工作經驗的應聘者就不會那麼簡單了,今天就來討論很多面試官喜歡問的Android的事件分發.

Android為什麼要有事件分發呢?因為它是按照層排列,他如何知道你點擊的哪一層呢,就需要用到事件分發了.

說到事件分發可能就會想起那三個威武的方法:事件分發(dispatchTouchEvent(MotionEvent ev))、事件攔截(onInterceptTouchEvent(MotionEvent ev))、事件響應(onTouchEvent(MotionEvent ev)),其中ViewGroup響應這三個方法,View要看它是否有子View,沒有子View時不響應事件攔截,Activity不響應事件攔截.

這裡先給出一張事件分發的流程圖


當然不是所有情況下都這麼走,當你的View和ViewGroup都是系統預設的情況下,是根據的流程走,只要View或者ViewGroup中的任何一個對事件感興趣,流程就不一定是什麼樣子了,這個需要具體問題具體分析

下面通過一個demo分析一下具體問題,demo只貼一下代碼,不提供代碼,希望自己動動手,寫寫,看看到底是什麼樣子的

我寫的demo一個有三部分,Activity,View,ViewGroup三部分,重寫了一下那三個威武的函數,當然像activity這樣的就不用寫事件攔截,學著靈活運用

1,activity代碼

package com.thea.guo;import android.os.Bundle;import android.app.Activity;import android.util.Log;import android.view.Menu;import android.view.MotionEvent;import android.view.View;import android.widget.Button;public class MainActivity extends Activity {Button button;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MainActivity.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MainActivity.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MainActivity.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MainActivity.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

2.view代碼

/** *  */package com.thea.guo.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.Button;import android.widget.TextView;/** * @author 子墨 * * 2015-1-15 */public class MyView extends TextView {public MyView(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyView.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyView.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyView.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyView.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

3.ViewGroup代碼

/** *  */package com.thea.guo.view;import android.content.Context;import android.util.AttributeSet;import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;/** * @author 子墨 * * 2015-1-15 */public class MyViewGroup extends LinearLayout {public MyViewGroup(Context context, AttributeSet attrs) {super(context, attrs);}@Overridepublic boolean dispatchTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.dispatchTouchEvent is up");break;}return super.dispatchTouchEvent(ev);}@Overridepublic boolean onInterceptTouchEvent(MotionEvent ev) {switch (ev.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.onInterceptTouchEvent is up");break;}return super.onInterceptTouchEvent(ev);}@Overridepublic boolean onTouchEvent(MotionEvent event) {switch (event.getAction()) {case MotionEvent.ACTION_DOWN:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is down");break;case MotionEvent.ACTION_MOVE:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is moving");break;case MotionEvent.ACTION_UP:Log.d("com.thea.guo", "MyViewGroup.onTouchEvent is up");break;}return super.onTouchEvent(event);}}

4.xml代碼

<com.thea.guo.view.MyViewGroup 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"     android:gravity="center">    <com.thea.guo.view.MyView        android:id="@+id/my_button"        android:layout_width="200dp"        android:layout_height="200dp"        android:text="@string/hello_world"         android:background="@android:color/holo_blue_bright">    </com.thea.guo.view.MyView></com.thea.guo.view.MyViewGroup>

以上就是全部代碼了,其實你還可以吧一部分代碼封裝一下更好,例如down,Move,up部分都是一樣的,你可以把這部分封裝.下面開始分析一下上文提到的特殊情況

~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

1.修改ViewGroup的dispatchTouchEvent(事件分發)返回值

(1)返回值為true

上面兩張圖片比較醒目的解釋了它的分發過程,首先從activity的dispatchTouchEvent開始分發,系統預設的情況下繼續分發,分發給ViewGroup的dispatchTouchEvent,ViewGroup的dispatchTouchEvent返回true,也就是說它對這個事件比較感興趣,它想留著自己處理,事件停止分發.

(2)返回值為false



同樣是從activity的dispatchTouchEvent開始分發,分發給ViewGroup的dispatchTouchEvent,ViewGroup的dispatchTouchEvent返回false,ViewGroup不感興趣,但是它也不配合你,他直接不給你往下傳遞了,這時候就需要onTouchEvent來處理了,由於view是從activity開始發起,所以就需要activity的OnTouchEvent來處理了

2.修改ViewGroup的onInterceptTouchEvent返回值

(1)返回值為true



還是從activity的dispatchTouchEvent開始分發,分發給ViewGroup的dispatchTouchEvent,ViewGroup判斷一下是否攔截,由於這裡onInterceptTouchEvent的返回值為true,不好意思它攔截了,它想讓它的OnTouchEvent處理這個事件,ViewGroup的OnTouchEvent處理完成後繼續向下傳遞給activity的OnTouchEvent

(2)返回值為false



是不是似曾相識啊,沒錯,ViewGroup中的onInterceptTouchEvent預設就是不攔截的,先從activity中的dispatchTouchEvent開始分發,分發給ViewGroup中的dispatchTouchEvent,然後判斷ViewGroup是否攔截,這裡返回false,表示它不攔截,然後繼續分發,分發給View中的dispatchTouchEvent,View下沒有子View了,於是他就直接給自己的onTouchEvent處理了,onTouchEvent對這個也不感興趣,繼續傳遞

3.修改View的dispatchTouchEvent返回值

(1)返回值為true



這裡還是那個分發過程,當分發到View時,它返回了true,也就是說它高度興趣,它想自己處理.

(2)返回值為false



還是那個配方還是那個味道,View中dispatchTouchEvent返回false,它直接不給分發了,留給OnTouch處理,由於view是從ViewGroup傳遞過來的,那也要ViewGroup的自個處理.

4.修改view中OnTouchEvent的返回值

(1)返回值為true



事件還是一如既往的傳遞,當傳遞到View中的OnTouchEvent時,返回true,它要say sorry了,不給你們傳遞了,到這它要自己處理了

(2)返回值為false



後面的OnTouchEvent跟view的都差不多了,這裡不再囉嗦,下面來個總結,結束這篇部落格


1.dispatchTouchEvent(事件分發)

當dispatchTouchEvent返回true時,由它自己處理

當dispatchTouchEvent返回false時,交給OnTouchEvent處理

系統預設的情況下,分發給onInterceptTouchEvent

2.onInterceptTouchEvent(事件攔截)

當onInterceptTouchEvent返回true,由他自己的OnTouchEvent處理

當onInterceptTouchEvent返回false,繼續分發

系統預設不攔截

3.onTouchEvent(事件響應)

當onTouchEvent返回true時自己處理

當onTouchEvent返回false,繼續傳遞

系統預設繼續傳遞

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.