1.? 怎么做到當(dāng)路徑上有一個(gè)ViewGroup攔截了Down事件之后,后續(xù)的move , up等事件就只交給它來(lái)處理,? 而不會(huì)再繼續(xù)往下走了?
2. ?個(gè)中主流控件, 包括FrameLayout, RelatvieLayout, LinearLayout, 等都是如何實(shí)現(xiàn)其 onTouchEvent, onInterceptTouchEvent, dispatchTouchEvent方法的.?"
有什么共性? ? 有什么區(qū)別?
-----上面提到的三個(gè)布局都沒(méi)有實(shí)現(xiàn)任何一個(gè)方法, 都是集成的ViewGroup中的邏輯, ? 而他們的直接父類, ViewGroup 也只實(shí)現(xiàn)了onInterceptTouchEvent() 和dispatchTouchEvent()
并且onInterceptTouchEvent()中基本上就是返回false,( 除了是鼠標(biāo)拖動(dòng)滾動(dòng)條的事件).
所以基本上, 分析的重點(diǎn)就在View.java和ViewGroup.java中的dispatchTouchEvent()方法.
ScrollView ?實(shí)現(xiàn)了自己的onInterceptTouchEvent()onTouchEvent() ? ?注意ScrollView 繼承了FrameLayout, 只支持豎向
onInterceptTouchEvent() 注釋說(shuō)的明白: 我們只關(guān)心當(dāng)前是不是正在被滑動(dòng)(dragging).
從實(shí)際效果上, 不管承載的控件們是否攔截或者處理了touchEvent, ScrollView本身都是會(huì)相應(yīng)滑動(dòng)的.
只要是move事件, 判斷出滑動(dòng)距離超過(guò)touchSlop之后, ?就認(rèn)為是在dragging. 那么就會(huì)返回true, 后續(xù)的事件都會(huì)自行處理.并且從這個(gè)返回true的事件開始, 會(huì)給子控件一個(gè)cancel.
再重申一遍重點(diǎn):
只有在move事件中, 并且當(dāng)累計(jì)滑動(dòng)距離(初始位置是在down時(shí)記錄的)已經(jīng)超過(guò)了touchSlop了, ?那么就會(huì)對(duì)子控件發(fā)出cancel事件, 對(duì)父控件調(diào)用:requestDisallowInterceptTouchEvent(true), 通知父親控件, 不要瞎摻和了.
上面說(shuō)的的對(duì)子控件發(fā)出cancel事件是怎么做到的? ?在這個(gè)事件的處理流程上, dispatchTouchEvent()中, 先調(diào)用自身的onInterceptTouchEvent()判斷自身是否攔截, 如上面分析, 如果攔截, 那么下面的intercepted變量為true, 所以接下來(lái)調(diào)用dispatchTransformedTouchEvent()時(shí), cancelChild參數(shù)為true, 里面會(huì)生成cancel事件, 并交給子控件處理. ?并且有一點(diǎn)注意:對(duì)于這個(gè)子控件, 處理完cancel事件之后, 后續(xù)的move, up事件也不會(huì)再交給它處理了. ? 中斷了, ?跟它沒(méi)關(guān)系了,
問(wèn)題: 那么上面說(shuō)的這點(diǎn)又是怎么做到的呢: ?怎么才做到cancel之后, 后續(xù)的事件都不給這個(gè)子控件了?
上面這個(gè)段代碼中高亮選中部分, ?會(huì)在子控件處理完cancel之后, 把mFirstTouchTarget置為null. 因?yàn)閷?duì)于ScrollView, 只有一個(gè)子控件, 所以next為null.
mFirstTouchTarget變成了null, 那下一次進(jìn)入dispatchTouchEvent()后, 處理就簡(jiǎn)單多了, 見(jiàn)下面代碼段:
對(duì)于之后的move事件, 并且mFirstTouchTarget已經(jīng)為null, ?直接設(shè)置intercepted為true. ? 同時(shí)后面的流程也就不再調(diào)用子控件的dispatchTouchEvent()
AbsListView 實(shí)現(xiàn)了自己的onInterceptTouchEvent()onTouchEvent()
----------未完