最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

關(guān)于Android觸摸事件分發(fā)的原理詳析

 更新時(shí)間:2022年01月09日 12:12:05   作者:靈劍山真人  
觸摸事件分發(fā)機(jī)制一直以來都是Android中比較重要的一大塊,自定義view,各種復(fù)雜的自定義手勢交互都與觸摸事件分發(fā)機(jī)制關(guān)系密,下面這篇文章主要給大家介紹了關(guān)于Android觸摸事件分發(fā)原理的相關(guān)資料,需要的朋友可以參考下

一:前言

最近在學(xué)Android的觸摸事件分發(fā),我覺得網(wǎng)上說的太雜太亂,而且有很多博客都有明顯的錯(cuò)誤。什么自頂向下分發(fā),自下向頂分發(fā),什么攔截又一直消費(fèi)什么什么之類,非常難懂。為了自己將來回顧可以更好的理解這塊知識,也為了后來之人可以更好的學(xué)習(xí),我寫下這篇博客。

二:說在前面的知識

  • 點(diǎn)擊,滑動,松手都是由MotionEvent這個(gè)類來表示。
  • 屏幕上的一個(gè)事件序列是指以一個(gè)MotionEvent.action_down按下開始,以若干個(gè)MotionEvent.action_move移動事件在中間,再以一個(gè)MotionEvent.action_up作為結(jié)束的事件流。
  • view group是view的子類。view group和view都有dispatchTouchEvent方法;view group有onTnterceptTouchEvent和onTouchEvent方法,view 只有onTouchEvent方法。

三:整體流程

1:activity

我們點(diǎn)擊屏幕的所有事件,都會被第一個(gè)接收。

public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();//是一個(gè)空方法,如果想知道按下了屏幕,可以重寫這個(gè)方法打印日志
        }
        if (getWindow().superDispatchTouchEvent(ev)) {//把這個(gè)事件傳給window屬性
            return true;
        }
        return onTouchEvent(ev);
    }

2:window就是PhoneWindow

每一個(gè)activity都會對應(yīng)一個(gè)PhoneWindow(在onCreate方法之前、activity內(nèi)部的attach方法中創(chuàng)建)。PhoneWindow含有一個(gè)decor view屬性(setContentView中創(chuàng)建),phone window把事件傳給decor view。 decor view繼承于view group。點(diǎn)擊事件現(xiàn)在傳到decor view這里,就開始view group的事件分發(fā)邏輯了。

3:view group

view group收到點(diǎn)擊事件, 進(jìn)入dispatchTouchEvent, 如果滿足以下二個(gè)條件中的任何一個(gè)條件:

  • 事件為down事件
  • 有一個(gè)子view或子view group在處理著事件流了
mFirstTouchTarget !=null

就進(jìn)入判斷,如果沒有被禁用攔截(子view調(diào)用parent.requestDisallowed....)就執(zhí)行, onInterceptTouchEvent代碼。

如果決定攔截,后面還會把mFirstTouchTarget置為null,這樣,之后就不會在調(diào)用onInterceptTouchEvent了。而且之后的事件流都會由這個(gè)view group的dispatchTouchEvent處理

如果不決定攔截,就遍歷子view、子view group,挨個(gè)調(diào)用它們的dispatchTouchEvent。如果沒有人接收,那就調(diào)用自己的super.dispatchTouchEventview group的super.dispatchTouchEvent就是自己view那部分 的 dispatchTouchEvent。

4:view

在view這一層,對于down事件,返回true就表示消費(fèi)這個(gè)down事件之后的序列。具體看圖。

 view調(diào)用setOnTouchLIstener可以設(shè)置OnTouchListener,重寫onTouch方法。從源碼中可以看出,若onTouch返回true,將不再回調(diào)onTouchEvent方法。不回調(diào)onTouchEvent的話,那onClickListener也不能回調(diào)了。

四:一些關(guān)鍵點(diǎn)

即使有view消費(fèi)著一組事件,事件流由底向上傳遞時(shí),依然會調(diào)用每一個(gè)view group的intercept攔截方法判斷是否攔截。當(dāng)一個(gè)view group遍歷它所有的子view沒有一個(gè)接收時(shí),就會進(jìn)入view模式,調(diào)用自己繼承于view的那一個(gè)dispatchTouchEvent方法。如果自己不接收,那會交給調(diào)用自己的dispatchTouchEvent的那個(gè)父view.

事件流沒有什么自上而下,就是自下而上的。

ViewGroup的實(shí)現(xiàn)負(fù)責(zé)將觸摸事件沿著控件樹向子控件進(jìn)行派發(fā),而View的實(shí)現(xiàn)則主要用于事件接收與處理工作。當(dāng)view group沒有子view接收時(shí),view group作為一個(gè)“view”去處理。

五:從源碼看觸摸事件分發(fā)

由于專欄關(guān)注自定義控件,所以關(guān)于系統(tǒng)如何從硬件獲取觸摸事件以及傳遞到Activity的dispatchTouchEvent就不詳細(xì)分解,下面將從Activity的dispatchTouchEvent方法來一步步看事件是如何被分發(fā)傳遞的:

Activity中的dispatchTouchEvent:

    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

其中onUserInteraction();是一個(gè)空實(shí)現(xiàn),是系統(tǒng)留給我們的一個(gè)修改事件分發(fā)的一個(gè)方法,這里可以忽略。

所以實(shí)際上Activity的dispatchTouchEvent方法是調(diào)用的PhoneWindow的superDispatchTouchEvent方法,如果superDispatchTouchEvent返回false,沒有消費(fèi)掉事件,那么才會再交給activity的onTouchEvent方法去處理,從這個(gè)角度來講,如果所有地方都沒有消費(fèi)掉事件,最后接收事件的會是Activity的onTouchEvent方法。

那么下面我們來看看PhoneWindow中的superDispatchTouchEvent方法:

    @Override
    public boolean superDispatchTouchEvent(MotionEvent event) {
        return mDecor.superDispatchTouchEvent(event);
    }

發(fā)現(xiàn)實(shí)際上調(diào)用的是DecorView對象mDecor的superDispatchTouchEvent方法,來看看DecorView的superDispatchTouchEvent方法:

        public boolean superDispatchTouchEvent(MotionEvent event) {
            return super.dispatchTouchEvent(event);
        }

調(diào)用的super.dispatchTouchEvent,而再來看看這個(gè)DecorView的繼承關(guān)系:

private final class DecorView extends FrameLayout implements RootViewSurfaceTaker

所以調(diào)用的是FrameLayout中的dispatchTouchEvent方法,而FrameLayout并沒有重寫dispatchTouchEvent方法,所以實(shí)際調(diào)用的是FrameLayout的父類 ---> ViewGroup中的dispatchTouchEvent方法,下面這個(gè)圖描述了從系統(tǒng)得到MotionEvent實(shí)際到傳遞給DecorView的super.dispatchTouchEvent的過程:

總結(jié)

到此這篇關(guān)于Android觸摸事件分發(fā)原理的文章就介紹到這了,更多相關(guān)Android觸摸事件分發(fā)原理內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java鎖機(jī)制Lock用法示例

    Java鎖機(jī)制Lock用法示例

    這篇文章主要介紹了Java鎖機(jī)制Lock用法,結(jié)合具體實(shí)例形式分析了Java鎖機(jī)制的相關(guān)上鎖、釋放鎖、隱式鎖、顯式鎖等概念與使用技巧,需要的朋友可以參考下
    2018-08-08
  • Spring Native項(xiàng)目實(shí)戰(zhàn)(體驗(yàn)79毫秒啟動springboot應(yīng)用)

    Spring Native項(xiàng)目實(shí)戰(zhàn)(體驗(yàn)79毫秒啟動springboot應(yīng)用)

    Spring Native是Spring提供的、制作native image的技術(shù)方案,本篇主要內(nèi)容是開發(fā)springboot應(yīng)用再構(gòu)建為native image的方法,通過Spring Native項(xiàng)目實(shí)戰(zhàn)讓大家體驗(yàn)79毫秒啟動springboot應(yīng)用,感興趣的朋友跟隨小編一起看看吧
    2021-05-05
  • 做java這么久了居然還不知道JSON的使用(一文帶你了解)

    做java這么久了居然還不知道JSON的使用(一文帶你了解)

    這篇文章主要介紹了做java這么久了居然還不知道JSON的使用(一文帶你了解),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-07-07
  • java使用jaxb操作xml示例

    java使用jaxb操作xml示例

    JAXB主要用來實(shí)現(xiàn)對象和XML之間的序列化和反序列化,關(guān)于JAXB的介紹就不多說了,這里主要總結(jié)下基本使用方法和一些注意事項(xiàng)
    2014-04-04
  • MyBatis實(shí)踐之DAO與Mapper

    MyBatis實(shí)踐之DAO與Mapper

    MyBatis前身是iBatis,是一個(gè)基于Java的數(shù)據(jù)持久層/對象關(guān)系映射(ORM)框架.通過本文給大家介紹MyBatis實(shí)踐之DAO與Mapper的相關(guān)知識,需要的朋友參考下吧
    2016-03-03
  • 詳解Java中的數(shù)組與字符串相關(guān)知識

    詳解Java中的數(shù)組與字符串相關(guān)知識

    這篇文章主要介紹了詳解Java中的數(shù)組與字符串相關(guān)知識,包括操作字符串的一些基本方法列舉,需要的朋友可以參考下
    2015-09-09
  • 如何解決springboot啟動的時(shí)候required a bean of type 'XXX' not be問題

    如何解決springboot啟動的時(shí)候required a bean of ty

    Spring Boot啟動失敗,提示缺少`UserDao`類型的Bean,解決方案一:為`UserDao`接口添加`@Mapper`注解,重新啟動;解決方案二:使用`@MapperScan`注解掃描Mapper接口所在的包
    2024-12-12
  • Java編程之雙重循環(huán)打印圖形

    Java編程之雙重循環(huán)打印圖形

    這篇文章主要介紹了Java編程之雙重循環(huán)打印圖形,屬于Java編程基礎(chǔ)練習(xí)部分,具有一定參考價(jià)值,需要的朋友可以了解下。
    2017-11-11
  • Java多線程之異步Future機(jī)制的原理和實(shí)現(xiàn)

    Java多線程之異步Future機(jī)制的原理和實(shí)現(xiàn)

    這篇文章主要為大家詳細(xì)介紹了Java多線程之異步Future機(jī)制的原理和實(shí)現(xiàn),感興趣的小伙伴們可以參考一下
    2016-08-08
  • springboot如何通過URL方式訪問外部資源

    springboot如何通過URL方式訪問外部資源

    這篇文章主要介紹了springboot如何通過URL方式訪問外部資源,具有很好的參考價(jià)值,希望對大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2021-12-12

最新評論

闻喜县| 双江| 托克托县| 滦平县| 奉新县| 贺兰县| 寿阳县| 芮城县| 长岭县| 甘孜| 青龙| 贵阳市| 石渠县| 分宜县| 洪洞县| 阜康市| 红安县| 灌阳县| 万年县| 莱阳市| 扎鲁特旗| 云霄县| 和田市| 临武县| 泉州市| 安徽省| 黄平县| 和顺县| 新津县| 格尔木市| 商城县| 云龙县| 历史| 阳春市| 万州区| 保德县| 新泰市| 昭平县| 静海县| 商都县| 怀远县|