? ? 前言:智能手機早已成為我們今天身邊必不可少的手持設(shè)備总寒,iOS和Android也是目前主流的二大移動操作系統(tǒng)贰您,當(dāng)然也有越來越多的開發(fā)者加入到移動開發(fā)的工作中來雇锡。我也是一名普通的Android碼農(nóng)搁痛,目前也在學(xué)習(xí)iOS開發(fā)中,有一些成長道路上的一些經(jīng)驗和教訓(xùn),很早就想動手記錄下來匿辩,再三下決心腰耙,終鼓起勇氣,敲起鍵盤铲球,有了下文挺庞,初次行文,文筆未免羞澀稼病,大神輕點噴~
? ? 我們都知道选侨,觸摸事件對我們移動App來說至關(guān)重要,人機交互從我們手指的各種觸摸手勢開始然走,手機屏幕檢測到我們的觸摸事件援制,手機操作系統(tǒng)會將這些觸摸事件通過回調(diào)框架提供的定義好的接口,讓我們App可以接收到這些觸摸事件芍瑞,從而開展我們自己的業(yè)務(wù)邏輯晨仑。在Android中,系統(tǒng)將觸摸事件包裝成MotionEvent對象拆檬,同時MotionEvent類內(nèi)部定義了ACTION_DOWN, ACTION_UP, ACTION_MOVE洪己,ACTION_CANCEL等常量來表示對應(yīng)觸摸事件,根據(jù)這些常量的名稱竟贯,我們很好理解它們對應(yīng)的含義答捕。下面,我們先提出我們的結(jié)論澄耍,然后我們一步步去驗證它們噪珊。
? ? 1.對于我們的App來說,觸摸事件傳遞的起點從Activity的dispathTouchEvent()回調(diào)方法開始齐莲。
? ? 我們上代碼驗證痢站,我們先寫一個最簡單的Activity,
? ? ?此時我們運行程序选酗,點擊按鈕阵难,控制臺會打印 “btn clicked!” 日志,一切正常芒填。
此時我們重寫Activity的dispatchTouchEvent方法呜叫,
? ? 再次運行程序,點擊按鈕殿衰,沒有打印日志朱庆,按鈕也沒有任何觸摸響應(yīng)。說明觸摸事件此時被屏蔽了闷祥,為了弄清楚到底怎么回事娱颊,就要去看看Activity的 dispatchTouchEvent方法的源碼。
? ? ?這里分三步,第一步箱硕,如果是觸摸開始類型ACTION_DOWN事件拴竹,會回調(diào)onUserInteraction()方法,所以在項目中可以考慮將一些需要用戶開始觸摸時就執(zhí)行的代碼放到此方法中剧罩;第二步栓拜,將觸摸事件ev傳遞給Activity窗口綁定的根布局rootView,如果rootView也有子布局惠昔,會一級一級傳遞幕与,具體過程我們下面會具體說明。所以如果所有布局的都沒有消費此觸摸事件ev舰罚,就會執(zhí)行第三步 纽门,調(diào)用Activity的onTouchEvent()方法,否則此觸摸事件ev在App層傳遞結(jié)束营罢。
? ? 上面我們講到Activity會將觸摸事件ev傳遞給根布局rootView,rootView有二種類型饼齿,View和ViewGroup饲漾。
? ? ?2.先說View,View觸摸事件的開始還是dispatchTouchEvent(), 然后View會先將ev傳遞給TouchListener消費缕溉,如果TouchListener沒有消費考传,就將ev傳遞給onTouchEvent,如果onTouchEvent沒有消費证鸥,就會向上傳遞給它的父容器或者Activity僚楞,
? ? ?還是上代碼,我們先驗證dispatchTouchEvent枉层,我們先自定義一個button泉褐,
? ? 此時,我們運行程序鸟蜡,按下按鈕膜赃,不要松開,滑動鼠標(biāo)(我用的模擬器)揉忘,真機此處換成手- ,-跳座,然后松開按鈕,查看控制臺打印日志:
? ? 也非常好理解泣矛,我們查看MotionEvent源代碼疲眷,ACTION_DONW = 0, ACTION_UP=1, ACTION_MOVE=2, 打印的日志與我們手指的觸摸操作完全一致,先是觸發(fā)了ACTION_DOWN事件您朽,然后是幾個ACTION_MOVE事件狂丝,最后是ACTION_UP事件。
? ? 接下來,我們給EventBtn添加onTouchListener美侦,并返回true
? ?運行App产舞,查看打印的日志,
? ? 我們看到菠剩,沒有打印 btn clicked日志易猫,驗證了我們說明的View事件傳遞的第一部分,觸摸事件ev具壮,優(yōu)先被onTouchListener消費掉了准颓,后面的onTouchEvent和onClickListener都不會再收到點擊的觸摸事件了。下面我們將onTouchListener的返回值改為false棺妓,并重寫EventBtn onTouchEvent方法攘已,并返回true。
? ?運行App怜跑,點擊按鈕样勃,查看打印的日志,
? ?這也驗證了我們關(guān)于View觸摸事件傳遞的第二部分性芬,觸摸事件ev優(yōu)先被onTouchListener消費峡眶,然后再讓傳遞給onTouchEvent消費。
? ?現(xiàn)在我們通過代碼驗證我們關(guān)于View觸摸事件傳遞機制的結(jié)論植锉,為了進一步佐證我們的結(jié)論辫樱,我們還得去查看View的框架源碼,我們打開View的源碼俊庇,找到dispatchTouchEvent方法狮暑,
? ? 看到源碼,很一目了然辉饱,框架先調(diào)用onTouchListener搬男,如果事件沒有被消費掉,再調(diào)用onTouchEvent鞋囊,最后result表示此觸摸事件是否被消費止后,作為返回值。
? ? 下一篇日記我們?nèi)W(xué)習(xí)關(guān)于ViewGroup的 消息傳遞溜腐,具體請聽下回分解~~