啥都不管,這里先安利一個非常好用的方法。簡直是解決事件沖突的利器啊。
getParent()(父親).request(請求)Disallow(不)Intercept(攔截)TouchEvent(touch事件)(true(同意)); getParent().requestDisallowInterceptTouchEvent(true);我是在自定義柱形圖的左右滑動跟側滑面板沖突的時候各種查閱找到的?;页:糜谩?/p>

Touch事件分發中有2個主角:ViewGroup和View。
ViewGroup 包 含 onInterceptTouchEvent 、 dispatchTouchEvent 、 onTouchEvent 三 個 相 關 事 件 。 View 包 含 dispatchTouchEvent、onTouchEvent 兩個相關事件。其中 ViewGroup 又繼承于 View。
ViewGroup 和 View 組成了一個樹狀結構
ViewGroup 和 View 組成了一個樹狀結構,根節點為 Activity 內部包含的一個 ViwGroup
觸摸事件由 Action_Down、Action_Move、Aciton_UP 組成,其中一次完整的觸摸事件中, Down 和 Up 都只有一個,Move 有若干個,可以為 0 個。
當 Acitivty 接收到 Touch 事件時,將遍歷子 View 進行 Down 事件的分發。ViewGroup 的遍 歷可以看成是遞歸的。分發的目的是為了找到真正要處理本次完整觸摸事件的 View,這個 View 會81 在 onTouchuEvent 結果返回 true。
當某個子 View 返回 true 時, 會中止 Down 事件的分發, 同時在 ViewGroup 中記錄該子 View。 接下去的 Move 和 Up 事件將由該子 View 直接進行處理。 由于子 View 是保存在 ViewGroup 中的, 多層 ViewGroup 的節點結構時,上級 ViewGroup 保存的會是真實處理事件的 View 所在的 ViewGroup 對象:如 ViewGroup0-ViewGroup1-TextView 的結構中,TextView 返回了 true,它將 被保存在 ViewGroup1 中,而 ViewGroup1 也會返回 true,被保存在 ViewGroup0 中。當 Move 和 UP 事件來時,會先從 ViewGroup0 傳遞至 ViewGroup1,再由 ViewGroup1 傳遞至 TextView。
當 ViewGroup 中所有子 View 都不捕獲 Down 事件時,將觸發 ViewGroup 自身的 onTouch 事件。觸發的方式是調用 super.dispatchTouchEvent 函數,即父類 View 的 dispatchTouchEvent 方法。在所有子 View 都不處理的情況下,觸發 Acitivity 的 onTouchEvent 方法。
onInterceptTouchEvent 有兩個作用:1.攔截 Down 事件的分發。2.中止 Up 和 Move 事件向 目標 View 傳遞,使得目標 View 所在的 ViewGroup 捕獲 Up 和 Move 事件
onInterceptTouchEvent:攔截
dispatchTouchEvent : 事件分發
onTouchEvent: 消費處理

上圖中不考慮攔截情況。事件分發順序就是:1-2-5-6-3-4.跟上面的那種圖是一樣的。同樣道理。假如6的 dispatchTouchEvent 返回true,那么3跟4就不會接收到。 規則:從外到里遍歷所有的子view,遇到是viewgroup的遍歷該viewgroup的所有子view
自定義一個button,繼承自button,打印onTouch和dispatchTouchEvent中的log(這里咱不考慮move事件)
public class MyButton extends Button { PRivate static final String TAG = "MyButton"; public MyButton(Context context) { super(context); } public MyButton(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("marc","My-Button-onTouchEvent-Action_DOWN"); break; case MotionEvent.ACTION_MOVE:// Logger.e("My-Button-onTouchEvent-Action_MOVE"); break; case MotionEvent.ACTION_UP: Log.i("marc","My-Button-onTouchEvent-Action_UP"); } return super.onTouchEvent(event); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("marc","My-Button-dispatchTouchEvent-Action_DOWN"); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: Log.i("marc","My-Button-dispatchTouchEvent-Action_DOWN"); } return super.dispatchTouchEvent(event); }}該button在xml中使用。在activity中調用.
mButton.setOnTouchListener(new View.OnTouchListener() { @Override public boolean onTouch(View v, MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("marc",TAG + "-onTouch-Action_DOWN"); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: Log.i("marc",TAG + "-onTouch-Action_DOWN"); } return false; } });調用activity的dispatchTouchEvent方法
@Overridepublic boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("marc",TAG + "-dispatchTouchEvent-Action_DOWN"); break; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: Log.i("marc",TAG + "-dispatchTouchEvent-Action_DOWN"); } return super.dispatchTouchEvent(event);}log日志可以看到先后順序

可以跟上面的相印證:從外向里依次分發
down事件
首先執行Activity的dispatchTouchEvent方法,進行事件的分發,actiivity就是上面2圖中的viewgroup(不考慮頂層布局啥的),這個時候遍歷它,activity中有個button的view。接著是button該view拿到該事件,然后執行dispatchTouchEvent進行分發。但是他自己是view,而不是viewgroup,沒有子viewbutton就執行自己的onTouch事件(上面有說onTouch事件要早于onTouchEvent事件,若onTouch返回true,就不執行onTouchEvent)接著是執行onTouchEvent事件down事件結束,開始up事件,跟上面流程一樣
首先執行Activity的dispatchTouchEvent方法,進行事件的分發,actiivity就是上面2圖中的viewgroup(不考慮頂層布局啥的),這個時候遍歷它,activity中有個button的view。接著是button該view拿到該事件,然后執行dispatchTouchEvent進行分發。但是他自己是view,而不是viewgroup,沒有子viewbutton就執行自己的onTouch事件(上面有說onTouch事件要早于onTouchEvent事件,若onTouch返回true,就不執行onTouchEvent)接著是執行onTouchEvent事件ps:最后才會響應button的onClick事件方法。這里沒有打印.
log日志如下:
02-09 16:01:10.483 18564-18564/? I/marc: MVPActivity-dispatchTouchEvent-Action_DOWN 02-09 16:01:10.523 18564-18564/? I/marc: MVPActivity-dispatchTouchEvent-Action_UP 02-09 16:01:10.523 18564-18564/? I/marc: MVPActivity-onTouchEvent-Action_UP可以看到在activity中的dispatchTouchEvent返回false后,就不進行下面的遍歷分發了。直接執行接下來的Up事件的分發。這里up事件雖然沒有返回false,但是沒有down事件了。后續的move和up事件也就沒了。所以直接還是執行activity的onTouchEvent事件
但是返回true跟返回false 日志一樣。那是因為在當前事件中,reture了,就跳出當前switch了。就不執行下面的了
大家經常聽過:在事件分發中,返回false表示不向下分發,返回true表示消費掉事件。這句話是針對ViewGroup說的。返回false不分發,返回true,消費掉也不分發了
log日志打印如下:
02-09 16:26:34.633 29520-29520/? I/marc: MVPActivity-dispatchTouchEvent-Action_DOWN02-09 16:26:34.643 29520-29520/? I/marc: My-Button-dispatchTouchEvent-Action_DOWN02-09 16:26:34.653 29520-29520/? I/marc: MVPActivity-onTouchEvent-Action_DOWN02-09 16:26:34.653 29520-29520/? I/marc: MVPActivity-dispatchTouchEvent-Action_UP02-09 16:26:34.653 29520-29520/? I/marc: MVPActivity-onTouchEvent-Action_UP可以看到到down事件分發到button的dispatchTouchEvent中時,返回了false,就不進行分發了。所以button的后續的move、up、onTouch、onTouchEvent就都不會響應。
log日志如下:
02-09 16:30:05.053 31599-31599/? I/marc: MVPActivity-dispatchTouchEvent-Action_DOWN02-09 16:30:05.053 31599-31599/? I/marc: My-Button-dispatchTouchEvent-Action_DOWN02-09 16:30:05.083 31599-31599/? I/marc: MVPActivity-dispatchTouchEvent-Action_UP02-09 16:30:05.083 31599-31599/? I/marc: My-Button-dispatchTouchEvent-Action_UP02-09 16:30:05.083 31599-31599/? I/marc: MVPActivity-onTouch-Action_UP02-09 16:30:05.083 31599-31599/? I/marc: My-Button-onTouchEvent-Action_UP可以看到button的dispatchTouchEvent 中的down返回true消費了。但是其他的move和up事件還是會繼續響應的。 同理:在up中返回false或者true是一樣的道理。唯一注意的是。up事件是一系列動作的結束,不像down事件是一系列動作的開始。
新聞熱點
疑難解答