Android 開發(fā)藝術(shù)探索筆記(十) 之 View 的事件分發(fā)機(jī)制以及滑動沖突解決

這是學(xué)習(xí) Android 一個很重要的知識點(diǎn)犀农,在日常工作和面試中都很經(jīng)常用到。下面我們好好來分析一下图贸。

1.點(diǎn)擊事件的傳遞規(guī)則

所謂的點(diǎn)擊事件的事件分發(fā)就是對 MotionEvent 事件的分發(fā)過程枉圃,即當(dāng)一個 MotionEvent 產(chǎn)生以后,系統(tǒng)需要把這個事件傳遞給一個具體的 View陨簇,這個傳遞過程就是分發(fā)過程。

這個過程有三個很重要的方法共同完成:

  • public boolean dispatchTouchEvent(MotionEvent event);

    這個方法用來進(jìn)行事件的分發(fā),如果事件能夠傳遞給當(dāng)前 View河绽,那么此方法一定會被調(diào)用己单,返回結(jié)果受當(dāng)前 View 的 onTouchEvent() 和下級 View 的 dispatchTouchEvent() 方法的影響,表示是否消耗當(dāng)前事件耙饰。

  • public boolean onInterceptTouchEvent(MotionEvent event);

    這個方法用來攔截觸摸事件的傳遞纹笼,如果返回 true,則不再將這個事件傳遞下去苟跪,觸摸事件將會轉(zhuǎn)給當(dāng)前 View 進(jìn)行處理廷痘,回調(diào)這個 View 的 onTouchEvent()。如果返回 false件已,則將這個觸摸事件繼續(xù)傳遞下去給子 View笋额。

  • public boolean onTouchEvent(MotionEvent event);

    這個方法表示是否消耗這個觸摸事件,假如返回 true篷扩,那么這個事件就已經(jīng)被該 View 消耗了兄猩,觸摸事件的傳遞到此為止,否則將會傳給該 View 的父容器鉴未。

    PS:當(dāng)一個 View 需要處理事件時枢冤,如果它設(shè)置了 OnTouchListener(注意,不要看成OnTouchEvent)铜秆,那么這個這個 OnTouchListeneronTouch() 方法將會被調(diào)用淹真,如果返回 true,那么 OnTouchEvent(MotionEvent event)方法將不會被調(diào)用连茧;如果返回 false趟咆,那么 OnTouchEvent(MotionEvent event)方法將會被調(diào)用。優(yōu)先級從高到低排序:OnTouchListener > OnTouchEvent(MotionEvent event)> OnClickListener 梅屉。

    當(dāng)一個點(diǎn)擊事件發(fā)生以后,它的傳遞順序就是:Activity -> PhoneWindow -> (調(diào)用 DecorView 的方法:mDecor.superDispatchTouchEvent())-> (由于 DecorView 繼承 FrameLayout鳞贷,所以這個觸摸事件會一直傳遞下去) View坯汤。

2.滑動沖突及解決辦法

滑動沖突有三種場景:

  • 1.外部滑動方向和內(nèi)部滑動方向不一樣

  • 2.外部滑動方向和內(nèi)部滑動方向相同

  • 3.上面兩種情況的嵌套

解決滑動沖突的套路:

  • 1、對于場景 1搀愧,處理的規(guī)則是:當(dāng)用戶左右滑動時惰聂,需要讓外層 View 攔截點(diǎn)擊事件;當(dāng)用戶上下滑動時咱筛,讓內(nèi)層 View 攔截點(diǎn)擊事件搓幌。其實(shí)就是根據(jù)滑動方向來判斷應(yīng)該由內(nèi)層 View 還是外層 View 來攔截事件。根據(jù)豎直方向滑動的距離和水平方向滑動的距離差來判斷是豎直方向滑動還是水平方向滑動迅箩。

  • 2溉愁、根據(jù)業(yè)務(wù)來確定什么狀態(tài)由外層 View 來處理滑動事件,什么狀態(tài)由內(nèi)層 View 處理滑動事件饲趋。

    推薦使用外部攔截法拐揭,即修改父容器需要攔截的事件撤蟆。
    示例代碼:

    @Override
    public boolean onInterceptTouchEvent(MotionEvent event) {
        boolean intercepted = false;
        int x = (int) event.getX();
        int y = (int) event.getY();
    
        switch (event.getAction()) {
        case MotionEvent.ACTION_DOWN: {
            intercepted = false;
            //滾動還沒完成的直接停止?jié)L動動畫
            if (!mScroller.isFinished()) {
                mScroller.abortAnimation();
                intercepted = true;
            }
            break;
        }
        case MotionEvent.ACTION_MOVE: {
            int deltaX = x - mLastXIntercept;
            int deltaY = y - mLastYIntercept;
    
            // 只攔截橫向的 MOVE 事件
            if (Math.abs(deltaX) > Math.abs(deltaY)) {
                intercepted = true;
            } else {
                intercepted = false;
            }
            break;
        }
        case MotionEvent.ACTION_UP: {
            intercepted = false;
            break;
        }
        default:
            break;
        }
    
        Log.d(TAG, "intercepted=" + intercepted);
        mLastX = x;
        mLastY = y;
        mLastXIntercept = x;
        mLastYIntercept = y;
    
        return intercepted;
    }
    
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市堂污,隨后出現(xiàn)的幾起案子家肯,更是在濱河造成了極大的恐慌,老刑警劉巖盟猖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件讨衣,死亡現(xiàn)場離奇詭異,居然都是意外死亡式镐,警方通過查閱死者的電腦和手機(jī)反镇,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來碟案,“玉大人愿险,你說我怎么就攤上這事〖鬯担” “怎么了辆亏?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長鳖目。 經(jīng)常有香客問我扮叨,道長,這世上最難降的妖魔是什么领迈? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任彻磁,我火速辦了婚禮,結(jié)果婚禮上狸捅,老公的妹妹穿的比我還像新娘衷蜓。我一直安慰自己,他們只是感情好尘喝,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布磁浇。 她就那樣靜靜地躺著,像睡著了一般朽褪。 火紅的嫁衣襯著肌膚如雪置吓。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天缔赠,我揣著相機(jī)與錄音衍锚,去河邊找鬼。 笑死嗤堰,一個胖子當(dāng)著我的面吹牛戴质,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼置森,長吁一口氣:“原來是場噩夢啊……” “哼斗埂!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起凫海,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤呛凶,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后行贪,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體漾稀,經(jīng)...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年建瘫,在試婚紗的時候發(fā)現(xiàn)自己被綠了崭捍。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡啰脚,死狀恐怖殷蛇,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情橄浓,我是刑警寧澤粒梦,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站荸实,受9級特大地震影響匀们,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜准给,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一泄朴、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧露氮,春花似錦祖灰、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至油讯,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間延欠,已是汗流浹背陌兑。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留由捎,地道東北人兔综。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親软驰。 傳聞我的和親對象是個殘疾皇子涧窒,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內(nèi)容