国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

事件分發

2019-11-09 15:48:09
字體:
來源:轉載
供稿:網友

android中的事件分發、焦點問題。

啥都不管,這里先安利一個非常好用的方法。簡直是解決事件沖突的利器啊。

getParent()(父親).request(請求)Disallow(不)Intercept(攔截)TouchEvent(touch事件)(true(同意)); getParent().requestDisallowInterceptTouchEvent(true);

我是在自定義柱形圖的左右滑動跟側滑面板沖突的時候各種查閱找到的?;页:糜谩?/p>

OnTouch和OnTouchEvent

這2個方法都是在View的dispatchTouchEvent中調用的,onTouch優先于onTouchEvent執行。如果再onTouch方法中通過返回true,那么事件就被消費掉,那么onTouchEvent將不會再執行.另外需要注意的是,onTouch 能夠得到執行需要兩個前提條件,第一 mOnTouchListener 的值不能為空,第二當前點擊的控件必須是 enable 的。因此如果你有一個控件是非 enable 的,那么給它注冊 onTouch 事件將永遠得不到執行。對于這一類控件,如果我們想要監聽它的 touch 事件,就必須通過在該控件中重寫 onTouchEvent 方法來實現。

Android 事件分發機制

Android 的事件分發機制主要是 Touch 事件分發,有兩個主角:ViewGroup 和 View。Activity的 Touch 事件事實上是調用它內部的 ViewGroup 的 Touch 事件,可以直接當成 ViewGroup 處理。View 在 ViewGroup 內, ViewGroup 也可以在其他 ViewGroup 內, 這時候把內部的 ViewGroup當成 View 來分析。先分析 ViewGroup 的處理流程:首先得有個結構模型概念:ViewGroup 和 View 組成了一棵樹形結構,最頂層為 Activity 的 ViewGroup,下面有若干的 ViewGroup 節點,每個節點之下又有若干的 ViewGroup 節點或者 View 節點,依次類推。如圖:

當一個 Touch 事件(觸摸事件為例)到達根節點,即 Acitivty 的 ViewGroup 時,它會依次下發,下發的過程是調用子 View(ViewGroup)的 dispatchTouchEvent 方法實現的。簡單來說,就是ViewGroup 遍歷它包含著的子 View,調用每個 View 的 dispatchTouchEvent 方法,而當子 View為 ViewGroup 時,又會通過調用 ViwGroup 的 dispatchTouchEvent 方法繼續調用其內部的 View的 dispatchTouchEvent 方法。上述例子中的消息下發順序是這樣的:1-2-5-6-7-3-4.dispatchTouchEvent 方法只負責事件的分發,它擁有 boolean 類型的返回值,當返回為 true 時,順序下發會中斷。在上述例子中如果5的 dispatchTouchEvent 返回結果為 true,那么6-7-3-4將都接收不到本次 Touch 事件。

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 事件

方法相關

viewgroup的相關事件有三個:onInterceptTouchEvent、dispatchTouchEvent和onTouchEventview的相關事件少一個onInterceptTouchEvent,只有dispatchTouchEvent和onTouchEvent兩個方法.

onInterceptTouchEvent:攔截

dispatchTouchEvent : 事件分發

onTouchEvent: 消費處理

上圖中不考慮攔截情況。事件分發順序就是:1-2-5-6-3-4.跟上面的那種圖是一樣的。同樣道理。假如6的 dispatchTouchEvent 返回true,那么3跟4就不會接收到。 規則:從外到里遍歷所有的子view,遇到是viewgroup的遍歷該viewgroup的所有子view

demo實踐

自定義一個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事件方法。這里沒有打印.

在activity中的修改dispatchTouchEvent down中返回false

@Overridepublic boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()) { case MotionEvent.ACTION_DOWN: Log.i("marc", TAG + "-dispatchTouchEvent-Action_DOWN"); //這里返回false,就不會繼續向下把down事件分到到子view,反言之,子view就不能夠響應。 return false; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: Log.i("marc", TAG + "-dispatchTouchEvent-Action_UP"); } return super.dispatchTouchEvent(event);}

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,消費掉也不分發了


修改MyButton的dispatchTouchEvent的MotionEvent.ACTION_DOWN返回false

@Overridepublic boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i("marc","My-Button-dispatchTouchEvent-Action_DOWN"); return false; case MotionEvent.ACTION_MOVE: break; case MotionEvent.ACTION_UP: Log.i("marc","My-Button-dispatchTouchEvent-Action_UP"); } return super.dispatchTouchEvent(event);}

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就都不會響應。

修改MyButton的dispatchTouchEvent的MotionEvent.ACTION_DOWN返回true

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事件是一系列動作的開始。


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 长汀县| 泾阳县| 文成县| 泗水县| 杂多县| 永丰县| 衡南县| 兴海县| 彩票| 如皋市| 黔江区| 山阳县| 陕西省| 措美县| 临高县| 周宁县| 清水河县| 尚义县| 通渭县| 沭阳县| 博乐市| 新建县| 咸阳市| 香港| 泗洪县| 潍坊市| 临夏县| 永仁县| 湘西| 班玛县| 甘孜| 武安市| 三都| 确山县| 巴彦淖尔市| 泰宁县| 西平县| 海安县| 时尚| 和平区| 福清市|