亚洲精品中文免费|亚洲日韩中文字幕制服|久久精品亚洲免费|一本之道久久免费

      
      

            <dl id="hur0q"><div id="hur0q"></div></dl>

                Framework事件機(jī)制-深扒onInterceptTouchEvent攔截流程解析

                Framework事件機(jī)制-深扒onInterceptTouchEvent攔截流程解析

                一、基本知識(shí)

                1.事件分發(fā)的三個(gè)函數(shù)

                事件的分發(fā) dispatchTouchEvent()

                事件的攔截 onInterceptTouchEvent()

                事件的處理(消費(fèi)) onTouchEvent()

                2.事件分發(fā)的對(duì)象

                被分發(fā)的對(duì)象是那些?被分發(fā)的對(duì)象是用戶觸摸屏幕而產(chǎn)生的點(diǎn)擊事件,事件主要包括:按下、滑動(dòng)、抬起與取消。這些事件被封裝成MotionEvent對(duì)象。

                MotionEvent.ACTION_DOWN 在屏幕按下時(shí) MotionEvent.ACTION_MOVE 在屏幕上滑動(dòng)時(shí) MotionEvent.ACTION_UP 在屏幕抬起時(shí) MotionEvent.ACTION_CANCLE 滑動(dòng)超出控件邊界時(shí)

                3.分發(fā)事件的組件

                分發(fā)事件的組件,也稱為分發(fā)事件者,包括Activity、View和ViewGroup。它們?nèi)叩囊话憬Y(jié)構(gòu)為:

                二、事件處理流程

                首先,我們需要了解事件處理中的幾個(gè)方法

                1、在ViewGroup中,事件分為dispatchTouchEvent(事件的分發(fā)),onInterceptTouchEvent(事件的攔截),onTouchEvent(事件的處理)。

                2、在View中,事件分為dispatchTouchEvent(事件的分發(fā)),onTouchEvent(事件的處理)。

                下面是demo的界面結(jié)構(gòu),它是由兩個(gè)自定義的ViewGroup和一個(gè)自定義的View組成,并分別重寫了它們的以上幾個(gè)方法。

                其中MyViewGroupA代碼如下:

                public class MyViewGroupA extends LinearLayout { public MyViewGroupA(Context context) { super(context); } public MyViewGroupA(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupA”,”dispatchTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupA”,”dispatchTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupA”,”dispatchTouchEvent_ACTION_UP”); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupA”,”onInterceptTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupA”,”onInterceptTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupA”,”onInterceptTouchEvent_ACTION_UP”); break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupA”,”onTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupA”,”onTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupA”,”onTouchEvent_ACTION_UP”); break; } return super.onTouchEvent(event); }}

                MyViewGroupB代碼如下:

                public class MyViewGroupB extends LinearLayout { public MyViewGroupB(Context context) { super(context); } public MyViewGroupB(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupB”,”dispatchTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupB”,”dispatchTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupB”,”dispatchTouchEvent_ACTION_UP”); break; } return super.dispatchTouchEvent(ev); } @Override public boolean onInterceptTouchEvent(MotionEvent ev) { switch (ev.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupB”,”onInterceptTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupB”,”onInterceptTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupB”,”onInterceptTouchEvent_ACTION_UP”); break; } return super.onInterceptTouchEvent(ev); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyViewGroupB”,”onTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyViewGroupB”,”onTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyViewGroupB”,”onTouchEvent_ACTION_UP”); break; } return super.onTouchEvent(event); }}

                MyView代碼如下:

                public class MyView extends View { public MyView(Context context) { super(context); } public MyView(Context context, AttributeSet attrs) { super(context, attrs); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyView”,”dispatchTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyView”,”dispatchTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyView”,”dispatchTouchEvent_ACTION_UP”); break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“MyView”,”onTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“MyView”,”onTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“MyView”,”onTouchEvent_ACTION_UP”); break; } return super.onTouchEvent(event); }}

                我們說(shuō)過(guò),事件傳遞是由上到下的,所以最外層的View首先對(duì)事件進(jìn)行操作。而我們最外層是Activity,所以事件也是從這里開(kāi)始。 Activity代碼如下:

                public class MainActivity extends AppCompatActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); } @Override public boolean dispatchTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“Activity”,”dispatchTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“Activity”,”dispatchTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“Activity”,”dispatchTouchEvent_ACTION_UP”); break; } return super.dispatchTouchEvent(event); } @Override public boolean onTouchEvent(MotionEvent event) { switch (event.getAction()){ case MotionEvent.ACTION_DOWN: Log.i(“Activity”,”onTouchEvent_ACTION_DOWN”); break; case MotionEvent.ACTION_MOVE: Log.i(“Activity”,”onTouchEvent_ACTION_MOVE”); break; case MotionEvent.ACTION_UP: Log.i(“Activity”,”onTouchEvent_ACTION_UP”); break; } return super.onTouchEvent(event); }}

                現(xiàn)在我們通過(guò)觸摸MyView開(kāi)始進(jìn)行分析。雖然dispatchTouchEvent是事件開(kāi)始的第一步,但是在開(kāi)發(fā)中,我們通常很少改寫它,所以我們下面只討論其他兩個(gè)方法。 1、對(duì)以上方法均不作處理,都返回super。這意味著我們既不攔截,也不消費(fèi)。

                大家看輸出結(jié)果:

                I/Activity: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWNI/MyView: dispatchTouchEvent_ACTION_DOWNI/MyView: onTouchEvent_ACTION_DOWNI/MyViewGroupB: onTouchEvent_ACTION_DOWNI/MyViewGroupA: onTouchEvent_ACTION_DOWNI/Activity: onTouchEvent_ACTION_DOWNI/Activity: dispatchTouchEvent_ACTION_MOVEI/Activity: onTouchEvent_ACTION_MOVEI/Activity: dispatchTouchEvent_ACTION_UPI/Activity: onTouchEvent_ACTION_UP

                結(jié)合輸出結(jié)果,我們可以總結(jié)出以下的結(jié)論:

                結(jié)合流程圖,不難發(fā)現(xiàn),如果我對(duì)事件既不攔截,也不消費(fèi),當(dāng)觸發(fā)ACTION_DOWN的時(shí)候,事件會(huì)經(jīng)過(guò)Activity——MyViewGroupA——MyViewGroupB——MyView一層層的向下進(jìn)行dispatchTouchEvent(分發(fā))—onInterceptTouchEvent(攔截)調(diào)用。當(dāng)?shù)竭_(dá)最底層MyView后,開(kāi)始觸發(fā)消費(fèi)操作,因?yàn)槲揖幌M(fèi),ACTION_DOWN將由底層一層層向上冒,移交上層處理。當(dāng)?shù)诌_(dá)最上層Activity后,說(shuō)明下層均不消費(fèi),之后觸發(fā)的ACTION_MOVE和ACTION_UP將不再向下層分發(fā)傳遞,直接交由Activity分發(fā)給自己進(jìn)行處理。

                2、我們將MyVIewGroupB的onInterceptTouchEvent返回值改為true,其他均是super。這意味著僅僅MyViewGroupB進(jìn)行事件攔截,但均無(wú)消費(fèi)

                輸出結(jié)果如下:

                I/Activity: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: onTouchEvent_ACTION_DOWNI/MyViewGroupA: onTouchEvent_ACTION_DOWNI/Activity: onTouchEvent_ACTION_DOWNI/Activity: dispatchTouchEvent_ACTION_MOVEI/Activity: onTouchEvent_ACTION_MOVEI/Activity: dispatchTouchEvent_ACTION_UPI/Activity: onTouchEvent_ACTION_UP

                結(jié)合輸出結(jié)果,總結(jié)如下:

                當(dāng)觸發(fā)ACTION_DOWN的時(shí)候,事件依然是從Activity開(kāi)始一層層向下傳遞,當(dāng)傳遞到MyViewGroupB時(shí),因?yàn)檫M(jìn)行了事件攔截,所以執(zhí)行完onInterceptTouchEvent后不再向下傳遞,而是直接交由MyViewGroupB的onTouchEvent進(jìn)行消費(fèi)處理。由于我們是只攔截,不消費(fèi),所以事件向上傳遞,交由上層處理,最終回到Activity。之后觸發(fā)的ACTION_MOVE和ACTION_UP也不再向下傳遞,直接交由Activity分發(fā)給自己處理。

                3、我們還是將MyViewGroupB的onInterceptTouchEvent返回super,但是將他的onTouchEvent返回true。這意味著我們不攔截,但是由MyViewGroupB進(jìn)行事件處理。

                輸出結(jié)果如下:

                I/Activity: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWNI/MyView: dispatchTouchEvent_ACTION_DOWNI/MyView: onTouchEvent_ACTION_DOWNI/MyViewGroupB: onTouchEvent_ACTION_DOWNI/Activity: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupA: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupA: onInterceptTouchEvent_ACTION_MOVEI/MyViewGroupB: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupB: onTouchEvent_ACTION_MOVEI/Activity: dispatchTouchEvent_ACTION_UPI/MyViewGroupA: dispatchTouchEvent_ACTION_UPI/MyViewGroupA: onInterceptTouchEvent_ACTION_UPI/MyViewGroupB: dispatchTouchEvent_ACTION_UPI/MyViewGroupB: onTouchEvent_ACTION_UP

                結(jié)合輸出結(jié)果,總結(jié)如下:

                可以看出,當(dāng)觸發(fā)ACTION_DOWN的時(shí)候,事件的分發(fā)傳遞過(guò)程和1的時(shí)候一樣,從Activity開(kāi)始一層層向下傳遞,最終傳遞到最底層MyView,觸發(fā)消費(fèi)操作,然后MyView將消費(fèi)操作移交上層處理,然后到達(dá)MyViewGroupB的onTouchEvent,并且進(jìn)行了消費(fèi)處理,事件處理到此不在向上移交。當(dāng)觸發(fā)ACTION_MOVE和ACTION_UP操作時(shí),事件依然需要由Activity開(kāi)始向下分發(fā)傳遞,但是當(dāng)傳遞到MyViewGroupB后,由于其消費(fèi)了ACTION_DOWN,事件將不再繼續(xù)向下分發(fā),而是直接由MyViewGroupB分發(fā)給自己的onTouchEvent進(jìn)行繼續(xù)處理。事件處理也不再向上移交。

                4、將MyViewGroupB的onInterceptTouchEvent和onTouchEvent的返回值均改為true。這意味著既攔截,又消費(fèi)。

                輸出結(jié)果如下:

                I/Activity: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupA: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: dispatchTouchEvent_ACTION_DOWNI/MyViewGroupB: onInterceptTouchEvent_ACTION_DOWNI/MyViewGroupB: onTouchEvent_ACTION_DOWNI/Activity: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupA: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupA: onInterceptTouchEvent_ACTION_MOVEI/MyViewGroupB: dispatchTouchEvent_ACTION_MOVEI/MyViewGroupB: onTouchEvent_ACTION_MOVEI/Activity: dispatchTouchEvent_ACTION_UPI/MyViewGroupA: dispatchTouchEvent_ACTION_UPI/MyViewGroupA: onInterceptTouchEvent_ACTION_UPI/MyViewGroupB: dispatchTouchEvent_ACTION_UPI/MyViewGroupB: onTouchEvent_ACTION_UP

                結(jié)合輸出結(jié)果,總結(jié)如下:

                當(dāng)觸發(fā)ACTION_DOWN的時(shí)候,依然從Activity開(kāi)始向下傳遞,當(dāng)?shù)竭_(dá)MyViewGroupB的是,因?yàn)樵趏nInterceptTouchEvent進(jìn)行了攔截操作,因此不再繼續(xù)向下分發(fā)傳遞,而是交由MyViewGroupB的onTouchEvent進(jìn)行處理消費(fèi)。MyViewGroupB的onTouchEvent返回的是true,說(shuō)明它決定對(duì)ACTION_DOWN進(jìn)行處理,因此事件也就不再移交上層處理。當(dāng)觸發(fā)ACTION_MOVE和ACTION_UP的時(shí)候,事件還是從Activity開(kāi)始向下傳遞,當(dāng)?shù)竭_(dá)MyViewGroupB的時(shí)候,由于之前進(jìn)行了攔截操作,因此,MyViewGroupB直接將事件分發(fā)給自己的onTouchEvent進(jìn)行處理,不在向下分發(fā)傳遞。事件處理也不再向上層移交。

                三、文末

                事件分發(fā)機(jī)制就猶如數(shù)學(xué)的定理是一樣道理的,只有記住定理,才能在具體應(yīng)用中具體分析,有人可能不知道在什么地方會(huì)用到,如果你做的項(xiàng)目中,比如有一個(gè)控件點(diǎn)擊不能反應(yīng),那么就有可能是事件分發(fā)的結(jié)果。

                至于對(duì)源碼的分析可能內(nèi)容比較復(fù)雜,內(nèi)容也多;需要我這套framework進(jìn)階學(xué)習(xí)全套筆記的可以前往私信我;發(fā)送“核心筆記”或“手冊(cè)”即可領(lǐng)??!整理不易!記得點(diǎn)贊分享哦!

                鄭重聲明:本文內(nèi)容及圖片均整理自互聯(lián)網(wǎng),不代表本站立場(chǎng),版權(quán)歸原作者所有,如有侵權(quán)請(qǐng)聯(lián)系管理員(admin#wlmqw.com)刪除。
                用戶投稿
                上一篇 2022年7月9日 21:17
                下一篇 2022年7月9日 21:18

                相關(guān)推薦

                • 分享4條發(fā)微商朋友圈的方法(微商朋友圈應(yīng)該怎么發(fā))

                  對(duì)于微商朋友來(lái)說(shuō),朋友圈的重要性不言而喻了。 那么微商的朋友圈到底該怎么發(fā)呢? 為什么同樣是經(jīng)營(yíng)一個(gè)朋友圈,有的微商看起來(lái)逼格滿滿,實(shí)際效果也不錯(cuò);而有的卻動(dòng)都不動(dòng)就被屏蔽甚至拉黑…

                  2022年11月27日
                • 《寶可夢(mèng)朱紫》夢(mèng)特性怎么獲得?隱藏特性獲取方法推薦

                  寶可夢(mèng)朱紫里有很多寶可夢(mèng)都是擁有夢(mèng)特性會(huì)變強(qiáng)的寶可夢(mèng),很多玩家不知道夢(mèng)特性怎么獲得,下面就給大家?guī)?lái)寶可夢(mèng)朱紫隱藏特性獲取方法推薦,感興趣的小伙伴一起來(lái)看看吧,希望能幫助到大家。 …

                  2022年11月25日
                • 《寶可夢(mèng)朱紫》奇魯莉安怎么進(jìn)化?奇魯莉安進(jìn)化方法分享

                  寶可夢(mèng)朱紫中的奇魯莉安要怎么進(jìn)化呢?很多玩家都不知道,下面就給大家?guī)?lái)寶可夢(mèng)朱紫奇魯莉安進(jìn)化方法分享,感興趣的小伙伴一起來(lái)看看吧,希望能幫助到大家。 奇魯莉安進(jìn)化方法分享 奇魯莉安…

                  2022年11月25日
                • 客服的崗位職責(zé)怎么寫(客服工作內(nèi)容及職責(zé))

                  各位小伙伴們大家周一好,又到了每周一給大家分享干貨內(nèi)容的時(shí)候啦~ 本期來(lái)跟大家分享一下客服工作管理流程以及客服崗位里面的每項(xiàng)職能崗位的核心細(xì)則,也是干貨滿滿推薦收藏~ 一.補(bǔ)償流程…

                  2022年11月25日
                • 中興Axon40 Ultra航天版將于11月29日正式發(fā)布

                  據(jù)中興手機(jī)官微爆料,中興Axon40 Ultra航天版將于11月29日正式發(fā)布,新機(jī)不僅會(huì)采用驍龍?zhí)幚砥鳎€將為大家?guī)?lái)一枚獨(dú)立安全芯片,獲得國(guó)密認(rèn)證,擁有安全專利布局,不僅可以大…

                  2022年11月24日
                • 三星tabs8+配置參數(shù) 三星tabs8+屏幕尺寸處理器介紹

                  三星Galaxy Tab S8+是2022年3月份上市的一款平板,有很多用戶想了解一下這款平板的配置參數(shù),下面我就給大家提供一下這款平板的參數(shù)配置。 三星Galaxy Tab S8…

                  2022年11月24日
                • 淘寶直播開(kāi)通后帶貨鏈接怎么做(淘寶直播需要開(kāi)通淘寶店鋪嗎)

                  直播帶貨無(wú)論是對(duì)于商家來(lái)說(shuō)還是主播收益都是非常可觀的,所以不少平臺(tái)都有直播帶貨功能,一些小伙伴也想加入淘寶直播,那么淘寶直播開(kāi)通后帶貨鏈接怎么做?下面小編為大家?guī)?lái)淘寶直播開(kāi)通后帶…

                  2022年11月24日
                • 事件營(yíng)銷案例

                  篇一成功營(yíng)銷案例小故事成功銷售案例小故事篇1模仿 一個(gè)人想做一套家具,就走到樹林里砍倒一棵樹,并動(dòng)手把它鋸成木板這個(gè)人鋸樹的時(shí)候,把樹干的一頭擱在樹墩上,自己騎在樹干上還往鋸開(kāi)的縫…

                  2022年11月24日
                • 《寶可夢(mèng)朱紫》暴飛龍?jiān)趺醋??暴飛龍獲得方法

                  寶可夢(mèng)朱紫暴飛龍位置在哪?在游戲中,很多玩家還不清楚暴飛龍具體要怎么樣獲得,其實(shí)獲得方法很簡(jiǎn)單,暴飛龍直接是沒(méi)得抓的,需要玩家從寶貝龍進(jìn)化得到,下面一起來(lái)看一下寶可夢(mèng)朱紫暴飛龍獲得…

                  2022年11月23日
                • 《寶可夢(mèng)朱紫》布土撥怎么進(jìn)化?布土撥進(jìn)化方法介紹

                  寶可夢(mèng)朱紫中,不同的寶可夢(mèng)有不同的進(jìn)化方法,其中布土撥的進(jìn)化方法是比較特殊的。很多玩家不知道寶可夢(mèng)朱紫布土撥怎么進(jìn)化,下面就帶來(lái)寶可夢(mèng)朱紫布土撥進(jìn)化方法介紹,一起來(lái)看看吧,希望能幫…

                  2022年11月23日

                聯(lián)系我們

                聯(lián)系郵箱:admin#wlmqw.com
                工作時(shí)間:周一至周五,10:30-18:30,節(jié)假日休息