Android中Touch事件的傳遞機制,androidtouch

來源:互聯網
上載者:User

Android中Touch事件的傳遞機制,androidtouch

由於之前對於android的事件傳遞機制不瞭解,今天正好不忙,趕緊抽出時間來理一下這方面的知識,本文結合demo,對android的事件傳遞機制進行分析。

在事件傳遞過程中,離不開以下三個方法:

1.dispatchTouchEvent 分發touchEvent,傳回值為true時表示TouchEvent被當前View處理,事件不會向下層傳遞(包括後續的onInterceptTouchEvent和onTouchEvent),

dispatchTouchEvent會收到後續的ACTION_MOVE和ACTION_UP事件

2.onInterceptTouchEvent 攔截touchEvent,返回true時表示當前View攔截了touchEvent,然後把事件交給當前View的onTouchEvent處理

3.onTouchEvent 處理TouchEvent,返回true時表示當前View消費了此事件,只有消費了前一個事件後才能收到後續事件。

 

為了弄清楚android在各層view的事件傳遞,我寫了一個小demo來分析Activity,ViewGroup,View之間的事件傳遞。

首先來看一下代碼,一個自訂View,畫了一個矩形,在dispatchTouchEvent,onTouchEvent中加入日誌方便解析。

 1 public class DrawRectView extends View { 2  3     private Paint mPaint; 4  5     public DrawRectView(Context context) { 6         super(context); 7         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG); 8     } 9 10     public DrawRectView(Context context, AttributeSet set) {11         super(context, set);12         mPaint = new Paint(Paint.ANTI_ALIAS_FLAG);13     }14 15     @Override16     public boolean dispatchTouchEvent(MotionEvent event) {17         Log.v(LogUtils.TAG, "DrawRectView dispatchTouchEvent action=" + event.getAction());18         return super.dispatchTouchEvent(event);19     }20 21 22     @Override23     protected void onDraw(Canvas canvas) {24         super.onDraw(canvas);25         mPaint.setColor(Color.YELLOW);26         canvas.drawRect(0, 0, 300, 300, mPaint);27     }28 29     @Override30     public boolean onTouchEvent(MotionEvent event) {31         Log.v(LogUtils.TAG, "DrawRectView onTouchEvent action=" + event.getAction());32         return super.onTouchEvent(event);33     }34 }

自訂Layout,同樣在相關的TouchEvent方法中加入log

 1 public class MyLayout extends RelativeLayout { 2  3     public MyLayout(Context context, AttributeSet attrs) { 4         super(context, attrs); 5     } 6  7     @Override 8     public boolean dispatchTouchEvent(MotionEvent ev) { 9         Log.v(LogUtils.TAG, "MyLayout dispatchTouchEvent action=" + ev.getAction());10         return super.dispatchTouchEvent(ev);11     }12 13     @Override14     public boolean onInterceptTouchEvent(MotionEvent ev) {15         Log.v(LogUtils.TAG, "MyLayout onInterceptTouchEvent action=" + ev.getAction());16         return super.onInterceptTouchEvent(ev);17     }18 19     @Override20     public boolean onTouchEvent(MotionEvent event) {21         Log.v(LogUtils.TAG, "MyLayout onTouchEvent event=" + event.getAction());22         return super.onTouchEvent(event);23     }

接下來是Activity與activity的布局

 1 public class TouchTestActivity extends Activity { 2  3     private DrawRectView mDrawRectView; 4  5     @Override 6     protected void onCreate(Bundle savedInstanceState) { 7         super.onCreate(savedInstanceState); 8         setContentView(R.layout.touch_test_activity); 9 10         mDrawRectView = (DrawRectView) findViewById(R.id.draw_rect_view);11         mDrawRectView.setOnTouchListener(new OnTouchListener() {12             @Override13             public boolean onTouch(View v, MotionEvent event) {14                 Log.v(LogUtils.TAG, "mDrawRectView OnTouchListener action=" + event.getAction());15                 return false;16             }17         });18     }19 20     @Override21     public boolean dispatchTouchEvent(MotionEvent ev) {22         Log.v(LogUtils.TAG, "TouchTestActivity dispatchTouchEvent action=" + ev.getAction());23         return super.dispatchTouchEvent(ev);24     }25 26     @Override27     public boolean onTouchEvent(MotionEvent event) {28         Log.v(LogUtils.TAG, "TouchTestActivity onTouchEvent action=" + event.getAction());29         return super.onTouchEvent(event);30     }31 }
 1 <com.yangy.test.custom_view.MyLayout xmlns:android="http://schemas.android.com/apk/res/android" 2     android:layout_width="match_parent" 3     android:layout_height="match_parent" > 4      5     <com.yangy.test.custom_view.DrawRectView 6         android:id="@+id/draw_rect_view" 7         android:layout_width="300dp" 8         android:layout_height="300dp" 9         android:layout_centerInParent="true" />10 11 </com.yangy.test.custom_view.MyLayout>

當我們按下矩形DrawRectView時,可以看到列印的log資訊如下,Android Touch事件自上到下傳遞,Activity-->ViewGroup-->View

11-24 15:19:40.659: V/--DEBUG--(32570): TouchTestActivity dispatchTouchEvent action=ACTION_DOWN
11-24 15:19:40.659: V/--DEBUG--(32570): MyLayout dispatchTouchEvent action=ACTION_DOWN
11-24 15:19:40.659: V/--DEBUG--(32570): MyLayout onInterceptTouchEvent action=ACTION_DOWN
11-24 15:19:40.659: V/--DEBUG--(32570): DrawRectView dispatchTouchEvent action=ACTION_DOWN
11-24 15:19:40.659: V/--DEBUG--(32570): mDrawRectView OnTouchListener action=ACTION_DOWN
11-24 15:19:40.669: V/--DEBUG--(32570): DrawRectView onTouchEvent action=ACTION_DOWN
11-24 15:19:40.669: V/--DEBUG--(32570): MyLayout onTouchEvent event=ACTION_DOWN
11-24 15:19:40.669: V/--DEBUG--(32570): TouchTestActivity onTouchEvent action=ACTION_DOWN
11-24 15:19:40.689: V/--DEBUG--(32570): TouchTestActivity dispatchTouchEvent action=ACTION_UP
11-24 15:19:40.689: V/--DEBUG--(32570): TouchTestActivity onTouchEvent action=ACTION_UP

根據log資訊,我們也就知道了整個View的事件傳遞流程,可用表示,這裡值得注意的是沒有任何View消耗掉ACTION_DOWN事件,

所以後續的ACTION_MOVE和ACTION_UP事件並不會向下傳遞了,這個從log中也可看出。

這時把DrawRectView的onTouchEvent方法返回true,則會出現什麼結果呢,接著看log

11-24 16:04:03.159: V/--DEBUG--(3037): TouchTestActivity dispatchTouchEvent action=ACTION_DOWN
11-24 16:04:03.159: V/--DEBUG--(3037): MyLayout dispatchTouchEvent action=ACTION_DOWN
11-24 16:04:03.159: V/--DEBUG--(3037): MyLayout onInterceptTouchEvent action=ACTION_DOWN
11-24 16:04:03.159: V/--DEBUG--(3037): DrawRectView dispatchTouchEvent action=ACTION_DOWN
11-24 16:04:03.159: V/--DEBUG--(3037): mDrawRectView OnTouchListener action=ACTION_DOWN
11-24 16:04:03.159: V/--DEBUG--(3037): DrawRectView onTouchEvent action=ACTION_DOWN


11-24 16:04:03.219: V/--DEBUG--(3037): TouchTestActivity dispatchTouchEvent action=ACTION_MOVE
11-24 16:04:03.219: V/--DEBUG--(3037): MyLayout dispatchTouchEvent action=ACTION_MOVE
11-24 16:04:03.219: V/--DEBUG--(3037): MyLayout onInterceptTouchEvent action=ACTION_MOVE
11-24 16:04:03.219: V/--DEBUG--(3037): DrawRectView dispatchTouchEvent action=ACTION_MOVE
11-24 16:04:03.219: V/--DEBUG--(3037): mDrawRectView OnTouchListener action=ACTION_MOVE
11-24 16:04:03.219: V/--DEBUG--(3037): DrawRectView onTouchEvent action=ACTION_MOVE


11-24 16:04:03.249: V/--DEBUG--(3037): TouchTestActivity dispatchTouchEvent action=ACTION_UP
11-24 16:04:03.249: V/--DEBUG--(3037): MyLayout dispatchTouchEvent action=ACTION_UP
11-24 16:04:03.249: V/--DEBUG--(3037): MyLayout onInterceptTouchEvent action=ACTION_UP
11-24 16:04:03.249: V/--DEBUG--(3037): DrawRectView dispatchTouchEvent action=ACTION_UP
11-24 16:04:03.249: V/--DEBUG--(3037): mDrawRectView OnTouchListener action=ACTION_UP
11-24 16:04:03.249: V/--DEBUG--(3037): DrawRectView onTouchEvent action=ACTION_UP

看來DrawRectView的onTouchEvent方法消費掉ACTION_DOWN事件後,ACTION_MOVE與ACTION_UP都傳遞過來了,而因為消費了事件,所以onTouchEvent 並不會向上傳遞

 如果在ViewGroup中攔截了TouchEvent事件又會怎麼樣呢,由來說明:

經過本文的說明後,相信你對於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.