Android ViewGroup事件分發機制
上一篇已經完整的解析了Android View的事件分發機制,今天給大家程式碼ViewGroup事件分發的原始碼解析~~凡是自定義ViewGroup實現各種滑動效果的,不可避免的會出現很多事件的衝突,對ViewGroup事件分發機制的瞭解,也有益於大家瞭解衝突產生的原因,以及對衝突進行處理~
1、案例
首先我們接著上一篇的程式碼,在程式碼中新增一個自定義的LinearLayout:
package com.example.zhy_event03; import android.content.Context; import android.util.AttributeSet; import android.util.Log; import android.view.MotionEvent; import android.widget.LinearLayout; public class MyLinearLayout extends LinearLayout { private static final String TAG = MyLinearLayout.class.getSimpleName(); public MyLinearLayout(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "dispatchTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "dispatchTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "dispatchTouchEvent ACTION_UP"); break; default: break; } return super.dispatchTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { int action = event.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "onTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "onTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "onTouchEvent ACTION_UP"); break; default: break; } return super.onTouchEvent(event); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { int action = ev.getAction(); switch (action) { case MotionEvent.ACTION_DOWN: Log.e(TAG, "onInterceptTouchEvent ACTION_DOWN"); break; case MotionEvent.ACTION_MOVE: Log.e(TAG, "onInterceptTouchEvent ACTION_MOVE"); break; case MotionEvent.ACTION_UP: Log.e(TAG, "onInterceptTouchEvent ACTION_UP"); break; default: break; } return super.onInterceptTouchEvent(ev); } @Override public void requestDisallowInterceptTouchEvent(boolean disallowIntercept) { Log.e(TAG, "requestDisallowInterceptTouchEvent "); super.requestDisallowInterceptTouchEvent(disallowIntercept); } }
繼承LinearLayout,然後複寫了與事件分發機制有關的程式碼,新增上了日誌的列印~
然後看我們的佈局檔案:
<com.example.zhy_event03.MyLinearLayout 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=".MainActivity" > <com.example.zhy_event03.MyButton android:id="@+id/id_btn" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="click me" /> </com.example.zhy_event03.MyLinearLayout>
MyLinearLayout中包含一個MyButton,MyButton都上篇部落格中已經出現過,這裡就不再貼程式碼了,不清楚可以去檢視~
然後MainActivity就是直接載入佈局,沒有任何程式碼~~~
直接執行我們的程式碼,然後點選我們的Button,依然是有意的MOVE一下,不然不會觸發MOVE事件,看一下日誌的輸出:
09-06 09:57:27.287: E/MyLinearLayout(959): dispatchTouchEvent ACTION_DOWN 09-06 09:57:27.287: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_DOWN 09-06 09:57:27.287: E/MyButton(959): dispatchTouchEvent ACTION_DOWN 09-06 09:57:27.297: E/MyButton(959): onTouchEvent ACTION_DOWN 09-06 09:57:27.297: E/MyButton(959): onTouchEvent ACTION_MOVE 09-06 09:57:27.327: E/MyLinearLayout(959): dispatchTouchEvent ACTION_MOVE 09-06 09:57:27.327: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_MOVE 09-06 09:57:27.337: E/MyButton(959): dispatchTouchEvent ACTION_MOVE 09-06 09:57:27.337: E/MyButton(959): onTouchEvent ACTION_MOVE 09-06 09:57:27.457: E/MyLinearLayout(959): dispatchTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyLinearLayout(959): onInterceptTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyButton(959): dispatchTouchEvent ACTION_UP 09-06 09:57:27.457: E/MyButton(959): onTouchEvent ACTION_UP
可以看到大體的事件流程為:
MyLinearLayout的dispatchTouchEvent -> MyLinearLayout的onInterceptTouchEvent -> MyButton的dispatchTouchEvent ->Mybutton的onTouchEvent
可以看出,在View上觸發事件,最先捕獲到事件的為View所在的ViewGroup,然後才會到View自身~
下面我們按照日誌的輸出,進入原始碼~
2、原始碼分析
ViewGroup - dispatchTouchEvent
1、ViewGroup - dispatchTouchEvent - ACTION_DOWN
首先是ViewGroup的dispatchTouchEvent方法:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!onFilterTouchEventForSecurity(ev)) {
return false;
}
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
final float scrolledXFloat = xf + mScrollX;
final float scrolledYFloat = yf + mScrollY;
final Rect frame = mTempRect;
boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (action == MotionEvent.ACTION_DOWN) {
if (mMotionTarget != null) {
// this is weird, we got a pen down, but we thought it was
// already down!
// XXX: We should probably send an ACTION_UP to the current
// target.
mMotionTarget = null;
}
// If we're disallowing intercept or if we're allowing and we didn't
// intercept
if (disallowIntercept || !onInterceptTouchEvent(ev)) {
// reset this event's action (just to protect ourselves)
ev.setAction(MotionEvent.ACTION_DOWN);
// We know we want to dispatch the event down, find a child
// who can handle it, start with the front-most child.
final int scrolledXInt = (int) scrolledXFloat;
final int scrolledYInt = (int) scrolledYFloat;
final View[] children = mChildren;
final int count = mChildrenCount;
for (int i = count - 1; i >= 0; i--) {
final View child = children[i];
if ((child.mViewFlags & VISIBILITY_MASK) == VISIBLE
|| child.getAnimation() != null) {
child.getHitRect(frame);
if (frame.contains(scrolledXInt, scrolledYInt)) {
// offset the event to the view's coordinate system
final float xc = scrolledXFloat - child.mLeft;
final float yc = scrolledYFloat - child.mTop;
ev.setLocation(xc, yc);
child.mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
if (child.dispatchTouchEvent(ev)) {
// Event handled, we have a target now.
mMotionTarget = child;
return true;
}
// The event didn't get handled, try the next view.
// Don't reset the event's location, it's not
// necessary here.
}
}
}
}
} ....//other code omitted
程式碼比較長,決定分段貼出,首先貼出的是ACTION_DOWN事件相關的程式碼。16行:進入ACTION_DOWN的處理
17-23行:將mMotionTarget置為null
26行:進行判斷:if(disallowIntercept || !onInterceptTouchEvent(ev))
兩種可能會進入IF程式碼段
1、當前不允許攔截,即disallowIntercept =true,
2、當前允許攔截但是不攔截,即disallowIntercept =false,但是onInterceptTouchEvent(ev)返回false ;
注:disallowIntercept 可以通過viewGroup.requestDisallowInterceptTouchEvent(boolean);進行設定,後面會詳細說;而onInterceptTouchEvent(ev)可以進行復寫。
36-57行:開始遍歷所有的子View
41行:進行判斷當前的x,y座標是否落在子View身上,如果在,47行,執行child.dispatchTouchEvent(ev),就進入了View的dispatchTouchEvent程式碼中了,如果不瞭解請參考:Android View的事件分發機制,當child.dispatchTouchEvent(ev)返回true,則為mMotionTarget=child;然後return true;
ViewGroup的ACTION_DOWN分析結束,總結一下:
ViewGroup實現捕獲到DOWN事件,如果程式碼中不做TOUCH事件攔截,則開始查詢當前x,y是否在某個子View的區域內,如果在,則把事件分發下去。
按照日誌,接下來到達ACTION_MOVE
2、ViewGroup - dispatchTouchEvent - ACTION_MOVE
首先我們原始碼進行刪減,只留下MOVE相關的程式碼:
@Override
public boolean dispatchTouchEvent(MotionEvent ev) {
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
final float scrolledXFloat = xf + mScrollX;
final float scrolledYFloat = yf + mScrollY;
final Rect frame = mTempRect;
boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
//...ACTION_DOWN
//...ACTIN_UP or ACTION_CANCEL
// The event wasn't an ACTION_DOWN, dispatch it to our target if
// we have one.
final View target = mMotionTarget;
// if have a target, see if we're allowed to and want to intercept its
// events
if (!disallowIntercept && onInterceptTouchEvent(ev)) {
//....
}
// finally offset the event to the target's coordinate system and
// dispatch the event.
final float xc = scrolledXFloat - (float) target.mLeft;
final float yc = scrolledYFloat - (float) target.mTop;
ev.setLocation(xc, yc);
return target.dispatchTouchEvent(ev);
}
18行:把ACTION_DOWN時賦值的mMotionTarget,付給target ;
23行:if (!disallowIntercept && onInterceptTouchEvent(ev)) 當前允許攔截且攔截了,才進入IF體,當然了預設是不會攔截的~這裡執行了onInterceptTouchEvent(ev)
28-30行:把座標系統轉化為子View的座標系統
32行:直接return target.dispatchTouchEvent(ev);
可以看到,正常流程下,ACTION_MOVE在檢測完是否攔截以後,直接呼叫了子View.dispatchTouchEvent,事件分發下去;
最後就是ACTION_UP了
3、ViewGroup - dispatchTouchEvent - ACTION_UP
public boolean dispatchTouchEvent(MotionEvent ev) {
if (!onFilterTouchEventForSecurity(ev)) {
return false;
}
final int action = ev.getAction();
final float xf = ev.getX();
final float yf = ev.getY();
final float scrolledXFloat = xf + mScrollX;
final float scrolledYFloat = yf + mScrollY;
final Rect frame = mTempRect;
boolean disallowIntercept = (mGroupFlags & FLAG_DISALLOW_INTERCEPT) != 0;
if (action == MotionEvent.ACTION_DOWN) {...}
boolean isUpOrCancel = (action == MotionEvent.ACTION_UP) ||
(action == MotionEvent.ACTION_CANCEL);
if (isUpOrCancel) {
mGroupFlags &= ~FLAG_DISALLOW_INTERCEPT;
}
final View target = mMotionTarget;
if(target ==null ){...}
if (!disallowIntercept && onInterceptTouchEvent(ev)) {...}
if (isUpOrCancel) {
mMotionTarget = null;
}
// finally offset the event to the target's coordinate system and
// dispatch the event.
final float xc = scrolledXFloat - (float) target.mLeft;
final float yc = scrolledYFloat - (float) target.mTop;
ev.setLocation(xc, yc);
return target.dispatchTouchEvent(ev);
}
17行:判斷當前是否是ACTION_UP
21,28行:分別重置攔截標誌位以及將DOWN賦值的mMotionTarget置為null,都UP了,當然置為null,下一次DOWN還會再賦值的~
最後,修改座標系統,然後呼叫target.dispatchTouchEvent(ev);
正常情況下,即我們上例整個程式碼的流程我們已經走完了:
1、ACTION_DOWN中,ViewGroup捕獲到事件,然後判斷是否攔截,如果沒有攔截,則找到包含當前x,y座標的子View,賦值給mMotionTarget,然後呼叫mMotionTarget.dispatchTouchEvent
2、ACTION_MOVE中,ViewGroup捕獲到事件,然後判斷是否攔截,如果沒有攔截,則直接呼叫mMotionTarget.dispatchTouchEvent(ev)
3、ACTION_UP中,ViewGroup捕獲到事件,然後判斷是否攔截,如果沒有攔截,則直接呼叫mMotionTarget.dispatchTouchEvent(ev)
當然了在分發之前都會修改下座標系統,把當前的x,y分別減去child.left 和 child.top ,然後傳給child;
3、關於攔截
1、如何攔截
上面的總結都是基於:如果沒有攔截;那麼如何攔截呢?
複寫ViewGroup的onInterceptTouchEvent方法:
@Override
public boolean onInterceptTouchEvent(MotionEvent ev)
{
int action = ev.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
//如果你覺得需要攔截
return true ;
case MotionEvent.ACTION_MOVE:
//如果你覺得需要攔截
return true ;
case MotionEvent.ACTION_UP:
//如果你覺得需要攔截
return true ;
}
return false;
}
預設是不攔截的,即返回false;如果你需要攔截,只要return true就行了,這要該事件就不會往子View傳遞了,並且如果你在DOWN retrun true ,則DOWN,MOVE,UP子View都不會捕獲事件;如果你在MOVE return true , 則子View在MOVE和UP都不會捕獲事件。
原因很簡單,當onInterceptTouchEvent(ev) return true的時候,會把mMotionTarget 置為null ;
2、如何不被攔截
如果ViewGroup的onInterceptTouchEvent(ev) 當ACTION_MOVE時return true ,即攔截了子View的MOVE以及UP事件;
此時子View希望依然能夠響應MOVE和UP時該咋辦呢?
Android給我們提供了一個方法:requestDisallowInterceptTouchEvent(boolean) 用於設定是否允許攔截,我們在子View的dispatchTouchEvent中直接這麼寫:
@Override
public boolean dispatchTouchEvent(MotionEvent event)
{
getParent().requestDisallowInterceptTouchEvent(true);
int action = event.getAction();
switch (action)
{
case MotionEvent.ACTION_DOWN:
Log.e(TAG, "dispatchTouchEvent ACTION_DOWN");
break;
case MotionEvent.ACTION_MOVE:
Log.e(TAG, "dispatchTouchEvent ACTION_MOVE");
break;
case MotionEvent.ACTION_UP:
Log.e(TAG, "dispatchTouchEvent ACTION_UP");
break;
default:
break;
}
return super.dispatchTouchEvent(event);
}
getParent().requestDisallowInterceptTouchEvent(true); 這樣即使ViewGroup在MOVE的時候return true,子View依然可以捕獲到MOVE以及UP事件。
從原始碼也可以解釋:
ViewGroup MOVE和UP攔截的原始碼是這樣的:
if (!disallowIntercept && onInterceptTouchEvent(ev)) {
final float xc = scrolledXFloat - (float) target.mLeft;
final float yc = scrolledYFloat - (float) target.mTop;
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
ev.setAction(MotionEvent.ACTION_CANCEL);
ev.setLocation(xc, yc);
if (!target.dispatchTouchEvent(ev)) {
// target didn't handle ACTION_CANCEL. not much we can do
// but they should have.
}
// clear the target
mMotionTarget = null;
// Don't dispatch this event to our own view, because we already
// saw it when intercepting; we just want to give the following
// event to the normal onTouchEvent().
return true;
}
當我們把disallowIntercept設定為true時,!disallowIntercept直接為false,於是攔截的方法體就被跳過了~
注:如果ViewGroup在onInterceptTouchEvent(ev) ACTION_DOWN裡面直接return true了,那麼子View是木有辦法的捕獲事件的~~~
4、如果沒有找到合適的子View
我們的例項,直接點選ViewGroup內的按鈕,當然直接很順利的走完整個流程;
但是有兩種特殊情況
1、ACTION_DOWN的時候,子View.dispatchTouchEvent(ev)返回的為false ;
如果你仔細看了,你會注意到ViewGroup的dispatchTouchEvent(ev)的ACTION_DOWN程式碼是這樣的
if (child.dispatchTouchEvent(ev)) {
// Event handled, we have a target now.
mMotionTarget = child;
return true;
}
只有在child.dispatchTouchEvent(ev)返回true了,才會認為找到了能夠處理當前事件的View,即mMotionTarget = child;
但是如果返回false,那麼mMotionTarget 依然是null
mMotionTarget 為null會咋樣呢?
其實ViewGroup也是View的子類,如果沒有找到能夠處理該事件的子View,或者乾脆就沒有子View;
那麼,它作為一個View,就相當於View的事件轉發了~~直接super.dispatchTouchEvent(ev);
原始碼是這樣的:
final View target = mMotionTarget;
if (target == null) {
// We don't have a target, this means we're handling the
// event as a regular view.
ev.setLocation(xf, yf);
if ((mPrivateFlags & CANCEL_NEXT_UP_EVENT) != 0) {
ev.setAction(MotionEvent.ACTION_CANCEL);
mPrivateFlags &= ~CANCEL_NEXT_UP_EVENT;
}
return super.dispatchTouchEvent(ev);
}
我們沒有一個能夠處理該事件的目標元素,意味著我們需要自己處理~~~就相當於傳統的View~
2、那麼什麼時候子View.dispatchTouchEvent(ev)返回的為true
如果你仔細看了上篇部落格,你會發現只要子View支援點選或者長按事件一定返回true~~
原始碼是這樣的:
if (((viewFlags & CLICKABLE) == CLICKABLE ||
(viewFlags & LONG_CLICKABLE) == LONG_CLICKABLE)) {
return true ; }
5、總結
關於程式碼流程上面已經總結過了~
1、如果ViewGroup找到了能夠處理該事件的View,則直接交給子View處理,自己的onTouchEvent不會被觸發;
2、可以通過複寫onInterceptTouchEvent(ev)方法,攔截子View的事件(即return true),把事件交給自己處理,則會執行自己對應的onTouchEvent方法
3、子View可以通過呼叫getParent().requestDisallowInterceptTouchEvent(true); 阻止ViewGroup對其MOVE或者UP事件進行攔截;
好了,那麼實際應用中能解決哪些問題呢?
比如你需要寫一個類似slidingmenu的左側隱藏menu,主Activity上有個Button、ListView或者任何可以響應點選的View,你在當前View上死命的滑動,選單欄也出不來;因為MOVE事件被子View處理了~ 你需要這麼做:在ViewGroup的dispatchTouchEvent中判斷使用者是不是想顯示選單,如果是,則在onInterceptTouchEvent(ev)攔截子View的事件;自己進行處理,這樣自己的onTouchEvent就可以順利展現出選單欄了~~
相關推薦
Android ViewGroup事件分發機制
上一篇已經完整的解析了Android View的事件分發機制,今天給大家程式碼ViewGroup事件分發的原始碼解析~~凡是自定義ViewGroup實現各種滑動效果的,不可避免的會出現很多事件的衝突,對ViewGroup事件分發機制的瞭解,也有益於大家瞭解衝突產生的原因,以及
Android View 事件分發機制原始碼詳解(ViewGroup篇)
前言 我們在學習View的時候,不可避免會遇到事件的分發,而往往遇到的很多滑動衝突的問題都是由於處理事件分發時不恰當所造成的。因此,深入瞭解View事件分發機制的原理,對於我們來說是很有必要的。由於View事件分發機制是一個比較複雜的機制,因此筆者將寫成兩篇文
Android View 事件分發機制 原始碼解析(ViewGroup篇)
1. 前言 android點選 事件一直以來都是很多安卓程式設計師的心病,之前通過demo模擬總結出一些經驗,但是不看原始碼的程式設計師不是好程式設計師,這段時間,系統的梳理了下整個事件傳遞的原始碼,希望可以幫助大家徹底理解andriod的點選
一張圖片讓你了解android的事件分發機制
text statistic trac avi oid csdn rac dsm tis 一張圖片讓你了解android的事件分發機制
Android開發——事件分發機制詳解---微信魚蝦蟹源碼搭建
lai reset 微信 影響 ren 事件分發機制 lis forum hlist 轉載請註明出處:http://h5.hxforum.com深入學習事件分發機制,是為了解決在Android開發中遇到的滑動沖突問題做準備。事件分發機制描述了用戶的手勢一系列事件是如何被An
ViewGroup事件分發機制解析
節點 view 效果 含義 oat pat ria reset poi 最近在看View的事件分發機制,感覺比復雜的地方就是ViewGrop的dispatchTouchEvent函數,便對照著源碼研究了一下。故名思意這個函數起到的作用就是分發事件,在具體分析之前還要說明幾個
Android View事件分發機制
作為程式猿,最不想 看的但是也不得不去看的就是原始碼!所謂知其然也要知其所以然,神祕的大佬曾經說過進階的方法就是READ THE FUCKING CODE! 認識MotionEvent 負責集中處理所有型別裝置的輸入事件.我們對螢幕的點選,滑動,擡起等一系的
"Android Touch事件分發機制"-Android面試必問"精華技能點"彙總
目錄: 一.事件分發中的 onTouch 和 onTouchEvent 有什麼區別,又該如何使用? 1.onTouch方法: 是View的 OnTouchListener介面中定義的方法。 當一個View綁定了OnTouchLister後,當有
Android面試題(27)-android的事件分發機制
今天開始寫一點關於view的知識,先從最基本的講吧,android的事件分發機制,其實在我看來,android的事件分發機制在現實生活中經常能看到,所以我覺得還是很好理解的;先看看生活中常見的一種情形吧;比如說,現在你所在的公司中有一項任務被派發下來了,專案經理把專案交給你的
完全理解Android TouchEvent事件分發機制(一)
本文能給你帶來和解決一些你模糊的Touch事件概念及用法 1.掌握View及ViewGroup的TouchEvent事件分發機制 2.為解決View滑動衝突及點選事件消費提供支援 3.為你解決面試中的一些問題。 Touch事件分發中只有兩個主角:Vi
android的事件分發機制
我們在面試的時候經常會被問到android事件分發機制,對於這個知識點其實也不算太難,關鍵在於不好理解,其實總結下來就兩句話: android事件分發過程:先由父類控制元件判斷是否攔截(onInterceptTouchEvent() is true or false),攔
一文讀懂Android View事件分發機制
Android View 雖然不是四大元件,但其並不比四大元件的地位低。而View的核心知識點事件分發機制則是不少剛入門同學的攔路虎。ScrollView巢狀RecyclerView(或者ListView)的滑動衝突這種老大難的問題的理論基礎就是事件分發機制。 事件
Android 簡述事件分發機制
1.ViewGroup有三個方法: Touch 事件相關方法 方法功能 標記 dispatchTouchEvent(MotionEvent ev) 事件分發 1 onInterceptTouchEvent(Motio
Android開發——事件分發機制詳解
0. 前言深入學習事件分發機制,是為了解決在Android開發中遇到的滑動衝突問題做準備。事件分發機制描述了使用者的手勢一系列事件是如何被Android系統傳遞並消費的。首先對事件分發機制進行概述:如果
面試:講講 Android 的事件分發機制
轉眼間 面試系列 已經到了第九期了,由於文章將會持續更新,導致標題難看性,所以以後的標題將更正為本文類似的格式。
Android中View和ViewGroup事件分發攔截機制完美分析
出自:http://www.cnblogs.com/linjzong/p/4191891.html Touch事件分發中只有兩個主角:ViewGroup和View。Activity的Touch事件事實上是呼叫它內部的ViewGroup的Touch事件,可以直接當成Vie
android 事件分發機制(ViewGroup)
昨天寫了一篇文章 是關於view 的事件分發機制 那麼今天我們將繼續上次未完成的話題,從原始碼的角度分析ViewGruop的事件分發。 首先確定下 ViewGroup 和Vew 有什麼區別 ViewGroup 顧名思義就是一個view
Android筆記-從ViewGroup的dispatchTouchEvent原始碼分析事件分發機制
前一篇文章:淺析了事件攔截機制 主要是從demo中看的現象總結的結論 文中涉及到以下方法 1. ViewGroup的三個方法: dispatchTouchEvent:事件分發 onInterceptTouchEvent:事件攔截 onTouchEve
Android事件分發機制原始碼分析下----ViewGroup事件分發分析
ViewGroup事件分發機制 上篇文章從原始碼的角度對View的事件分發進行了分析,這篇文章繼續對事件分發進行介紹,從原始碼的角度分析ViewGroup的事件分發,從繼承關係看ViewGroup也屬於View的一種,但它的內部可以放置View,簡單的結論我
Android中ViewGroup、View事件分發機制原始碼分析總結(雷驚風)
1.概述 很長時間沒有回想Android中的事件分發機制了,開啟目前的原始碼發現與兩三年前的實現程式碼已經不一樣了,5.0以後發生了變化,更加複雜了,但是萬變不離其宗,實現原理還是一樣的,在這裡將5.0以前的時間分發機制做一下原始碼剖析及總結。會涉及到幾個方