René's URL Explorer Experiment


Title: Android Touch事件分发机制系列一基本流程梳理 · Issue #11 · HankCoder/BlogAndCode · GitHub

Open Graph Title: Android Touch事件分发机制系列一基本流程梳理 · Issue #11 · HankCoder/BlogAndCode

X Title: Android Touch事件分发机制系列一基本流程梳理 · Issue #11 · HankCoder/BlogAndCode

Description: Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。 View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。 ViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。V...

Open Graph Description: Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。 View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。 ViewGroup的相关事件有三个:onInterceptTouc...

X Description: Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。 View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。 ViewGroup的相关事件有三个:onInterceptTouc...

Opengraph URL: https://github.com/HankCoder/BlogAndCode/issues/11

X: @github

direct link

Domain: github.com


Hey, it has json ld scripts:
{"@context":"https://schema.org","@type":"DiscussionForumPosting","headline":"Android Touch事件分发机制系列一基本流程梳理","articleBody":"Touch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。\r\n\r\nView在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。\r\n\r\nViewGroup的相关事件有三个:onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent。View的相关事件只有两个:dispatchTouchEvent、onTouchEvent。\r\n\r\n先分析ViewGroup的处理流程:首先得有个结构模型概念:ViewGroup和View组成了一棵树形结构,最顶层为Activity的ViewGroup,下面有若干的ViewGroup节点,每个节点之下又有若干的ViewGroup节点或者View节点,依次类推。如图:\r\n![image](https://user-images.githubusercontent.com/28669743/31529718-91cf1884-afa0-11e7-845d-8cf174fba496.png)\r\n当一个Touch事件(触摸事件为例)到达根节点,即Acitivty的ViewGroup时,它会依次下发,下发的过程是调用子View(ViewGroup)的dispatchTouchEvent方法实现的。简单来说,就是ViewGroup遍历它包含着的子View,调用每个View的dispatchTouchEvent方法,而当子View为ViewGroup时,又会通过调用ViwGroup的dispatchTouchEvent方法继续调用其内部的View的dispatchTouchEvent方法。上述例子中的消息下发顺序是这样的:①-②-⑤-⑥-⑦-③-④。dispatchTouchEvent方法只负责事件的分发,它拥有boolean类型的返回值,当返回为true时,顺序下发会中断。在上述例子中如果⑤的dispatchTouchEvent返回结果为true,那么⑥-⑦-③-④将都接收不到本次Touch事件。来个简单版的代码加深理解:\r\n\r\n```\r\n /**\r\n     * ViewGroup\r\n     * @param ev\r\n     * @return\r\n     */\r\n    public boolean dispatchTouchEvent(MotionEvent ev){\r\n        ....//其他处理,在此不管\r\n        View[] views=getChildView();\r\n        for(int i=0;i\u003cviews.length;i++){\r\n           //判断下Touch到屏幕上的点在该子View上面 \r\n            if(...){\r\n            if(views[i].dispatchTouchEvent(ev))\r\n              return true;\r\n             }\r\n        }\r\n        ...//其他处理,在此不管\r\n    }\r\n    /**\r\n     * View\r\n     * @param ev\r\n     * @return\r\n     */\r\n    public boolean dispatchTouchEvent(MotionEvent ev){\r\n        ....//其他处理,在此不管\r\n        return false;\r\n    }\r\n```\r\n在此可以看出,ViewGroup的dispatchTouchEvent是真正在执行“分发”工作,而View的dispatchTouchEvent方法,并不执行分发工作,或者说它分发的对象就是自己,决定是否把touch事件交给自己处理,而处理的方法,便是onTouchEvent事件,事实上子View的dispatchTouchEvent方法真正执行的代码是这样的\r\n\r\n```\r\n/**\r\n     * View\r\n     * @param ev\r\n     * @return\r\n     */\r\n    public boolean dispatchTouchEvent(MotionEvent ev){\r\n        ....//其他处理,在此不管\r\n        return onTouchEvent(event);\r\n    }\r\n\r\n```\r\n一般情况下,我们不该在普通View内重写dispatchTouchEvent方法,因为它并不执行分发逻辑。当Touch事件到达View时,我们该做的就是是否在onTouchEvent事件中处理它。\r\n\r\n那么,ViewGroup的onTouchEvent事件是什么时候处理的呢?当ViewGroup所有的子View都返回false时,onTouchEvent事件便会执行。由于ViewGroup是继承于View的,它其实也是通过调用View的dispatchTouchEvent方法来执行onTouchEvent事件。\r\n\r\n \r\n\r\n在目前的情况看来,似乎只要我们把所有的onTouchEvent都返回false,就能保证所有的子控件都响应本次Touch事件了。但必须要说明的是,这里的Touch事件,只限于Acition_Down事件,即触摸按下事件,而Aciton_UP和Action_MOVE却不会执行。事实上,一次完整的Touch事件,应该是由一个Down、一个Up和若干个Move组成的。Down方式通过dispatchTouchEvent分发,分发的目的是为了找到真正需要处理完整Touch请求的View。当某个View或者ViewGroup的onTouchEvent事件返回true时,便表示它是真正要处理这次请求的View,之后的Aciton_UP和Action_MOVE将由它处理。当所有子View的onTouchEvent都返回false时,这次的Touch请求就由根ViewGroup,即Activity自己处理了。\r\n\r\n看看改进后的ViewGroup的dispatchTouchEvent方法\r\n\r\n```\r\nView mTarget=null;//保存捕获Touch事件处理的View\r\n    public boolean dispatchTouchEvent(MotionEvent ev) {\r\n\r\n        //....其他处理,在此不管\r\n        \r\n        if(ev.getAction()==KeyEvent.ACTION_DOWN){\r\n            //每次Down事件,都置为Null\r\n\r\n            if(!onInterceptTouchEvent()){\r\n            mTarget=null;\r\n            View[] views=getChildView();\r\n            for(int i=0;i\u003cviews.length;i++){\r\n                if(views[i].dispatchTouchEvent(ev))\r\n                    mTarget=views[i];\r\n                    return true;\r\n            }\r\n          }\r\n        }\r\n        //当子View没有捕获down事件时,ViewGroup自身处理。这里处理的Touch事件包含Down、Up和Move\r\n        if(mTarget==null){\r\n            return super.dispatchTouchEvent(ev);\r\n        }\r\n        //...其他处理,在此不管\r\n        if(onInterceptTouchEvent()){\r\n         //...其他处理,在此不管    \r\n         }\r\n//这一步在Action_Down中是不会执行到的,只有Move和UP才会执行到。\r\n        return mTarget.dispatchTouchEvent(ev);\r\n\r\n    }\r\n ```\r\n\r\nViewGroup还有个onInterceptTouchEvent,看名字便知道这是个拦截事件。这个拦截事件需要分两种情况来说明:\r\n\r\n1.假如我们在某个ViewGroup的onInterceptTouchEvent中,将Action为Down的Touch事件返回true,那便表示将该ViewGroup的所有下发操作拦截掉,这种情况下,mTarget会一直为null,因为mTarget是在Down事件中赋值的。由于mTarge为null,该ViewGroup的onTouchEvent事件被执行。这种情况下可以把这个ViewGroup直接当成View来对待。\r\n\r\n2.假如我们在某个ViewGroup的onInterceptTouchEvent中,将Acion为Down的Touch事件都返回false,其他的都返回True,这种情况下,Down事件能正常分发,若子View都返回false,那mTarget还是为空,无影响。若某个子View返回了true,mTarget被赋值了,在Action_Move和Aciton_UP分发到该ViewGroup时,便会给mTarget分发一个Action_Delete的MotionEvent,同时清空mTarget的值,使得接下去的Action_Move(如果上一个操作不是UP)将由ViewGroup的onTouchEvent处理。\r\n\r\n情况一用到的比较多,情况二个人还未找到使用场景。\r\n\r\n从头到尾总结一下:\r\n\r\n1.Touch事件分发中只有两个主角:ViewGroup和View。ViewGroup包含onInterceptTouchEvent、dispatchTouchEvent、onTouchEvent三个相关事件。View包含dispatchTouchEvent、onTouchEvent两个相关事件。其中ViewGroup又继承于View。\r\n\r\n2.ViewGroup和View组成了一个树状结构,根节点为Activity内部包含的一个ViwGroup。\r\n\r\n3.触摸事件由Action_Down、Action_Move、Aciton_UP组成,其中一次完整的触摸事件中,Down和Up都只有一个,Move有若干个,可以为0个。\r\n\r\n4.当Acitivty接收到Touch事件时,将遍历子View进行Down事件的分发。ViewGroup的遍历可以看成是递归的。分发的目的是为了找到真正要处理本次完整触摸事件的View,这个View会在onTouchuEvent结果返回true。\r\n\r\n5.当某个子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。\r\n\r\n6.当ViewGroup中所有子View都不捕获Down事件时,将触发ViewGroup自身的onTouch事件。触发的方式是调用super.dispatchTouchEvent函数,即父类View的dispatchTouchEvent方法。在所有子View都不处理的情况下,触发Acitivity的onTouchEvent方法。\r\n\r\n7.onInterceptTouchEvent有两个作用:1.拦截Down事件的分发。2.中止Up和Move事件向目标View传递,使得目标View所在的ViewGroup捕获Up和Move事件。\r\n\r\n \r\n\r\n另外,上文所列出的代码并非真正的源码,只是概括了源码在事件分发处理中的核心处理流程,真正源码各位可以自己去看,包含了更丰富的内容。\r\n\r\n 补充:\r\n\r\n“触摸事件由Action_Down、Action_Move、Aciton_UP组成,其中一次完整的触摸事件中,Down和Up都只有一个,Move有若干个,可以为0个。”,这里补充下其实UP事件是可能为0个的。\r\n\r\n \r\n\r\n最近刚好在做一个手势放大缩小移动图片的Demo,对此有了更多的理解。对于onInterceptTouchEvent事件,它的应用场景在很多带scroll效果的ViewGroup中都有体现。设想一下再一个ViewPager中,每个Item都是个ImageView,我们需要对这些ImageView做Matrix操作,这不可避免要捕获掉Touch事件,但是我们又需要做到不影响ViewPager翻页效果,这又必须保证ViewPager能捕获到Move事件,于是,ViewPager的onInterceptTouchEvent会对Move事件做一个过滤,当适当条件的Move事件(持续若干事件或移动若干距离,这里我没读源码只是猜测)触发时,并会拦截掉,返回子View一个Action_Cancel事件。这个时候子View就没有Up事件了,很多需要在Up中处理的事物要转到Cancel中处理。","author":{"url":"https://github.com/HankCoder","@type":"Person","name":"HankCoder"},"datePublished":"2017-10-20T04:13:57.000Z","interactionStatistic":{"@type":"InteractionCounter","interactionType":"https://schema.org/CommentAction","userInteractionCount":0},"url":"https://github.com/11/BlogAndCode/issues/11"}

route-pattern/_view_fragments/issues/show/:user_id/:repository/:id/issue_layout(.:format)
route-controllervoltron_issues_fragments
route-actionissue_layout
fetch-noncev2:d77924f7-b569-cf9c-2280-0bb36623869b
current-catalog-service-hash81bb79d38c15960b92d99bca9288a9108c7a47b18f2423d0f6438c5b7bcd2114
request-id8E8C:8CD90:C4E802:11887D9:6A589027
html-safe-nonceed873912d091e381ec849663ac967e266c2d6844ffbd1b31de1e4926b7769211
visitor-payloadeyJyZWZlcnJlciI6IiIsInJlcXVlc3RfaWQiOiI4RThDOjhDRDkwOkM0RTgwMjoxMTg4N0Q5OjZBNTg5MDI3IiwidmlzaXRvcl9pZCI6IjYxNjg1OTU4OTgxODY2MzMyNTUiLCJyZWdpb25fZWRnZSI6ImlhZCIsInJlZ2lvbl9yZW5kZXIiOiJpYWQifQ==
visitor-hmac7f16884150117947c5216dcf09f160dad46340bc9689a43ffeebe7ed189dccff
hovercard-subject-tagissue:267059131
github-keyboard-shortcutsrepository,issues,copilot
google-site-verificationApib7-x98H0j5cPqHWwSMm6dNU4GmODRoqxLiDzdx9I
octolytics-urlhttps://collector.github.com/github/collect
analytics-location///voltron/issues_fragments/issue_layout
fb:app_id1401488693436528
apple-itunes-appapp-id=1477376905, app-argument=https://github.com/_view_fragments/issues/show/HankCoder/BlogAndCode/11/issue_layout
twitter:imagehttps://opengraph.githubassets.com/6dda679d9353b939431f1bb33b81586452156cc39eceb54b527f4a45e14f327a/HankCoder/BlogAndCode/issues/11
twitter:cardsummary_large_image
og:imagehttps://opengraph.githubassets.com/6dda679d9353b939431f1bb33b81586452156cc39eceb54b527f4a45e14f327a/HankCoder/BlogAndCode/issues/11
og:image:altTouch事件分发中只有两个主角:ViewGroup和View。Activity的Touch事件事实上是调用它内部的ViewGroup的Touch事件,可以直接当成ViewGroup处理。 View在ViewGroup内,ViewGroup也可以在其他ViewGroup内,这时候把内部的ViewGroup当成View来分析。 ViewGroup的相关事件有三个:onInterceptTouc...
og:image:width1200
og:image:height600
og:site_nameGitHub
og:typeobject
og:author:usernameHankCoder
hostnamegithub.com
expected-hostnamegithub.com
None5f2a0c7865178af3d91dd9f13b0cdfc3c73a2529c873d2780bb4c01271a57ec6
turbo-cache-controlno-preview
go-importgithub.com/HankCoder/BlogAndCode git https://github.com/HankCoder/BlogAndCode.git
octolytics-dimension-user_id10301539
octolytics-dimension-user_loginHankCoder
octolytics-dimension-repository_id83747204
octolytics-dimension-repository_nwoHankCoder/BlogAndCode
octolytics-dimension-repository_publictrue
octolytics-dimension-repository_is_forkfalse
octolytics-dimension-repository_network_root_id83747204
octolytics-dimension-repository_network_root_nwoHankCoder/BlogAndCode
turbo-body-classeslogged-out env-production page-responsive
disable-turbofalse
browser-stats-urlhttps://api.github.com/_private/browser/stats
browser-errors-urlhttps://api.github.com/_private/browser/errors
release8aae7b8d6caacacf5c66eaeb2702d8dc88d85b4a
ui-targetfull
theme-color#1e2327
color-schemelight dark

Links:

Skip to contenthttps://github.com/HankCoder/BlogAndCode/issues/11#start-of-content
https://github.com/
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FHankCoder%2FBlogAndCode%2Fissues%2F11
GitHub CopilotWrite better code with AIhttps://github.com/features/copilot
GitHub Copilot appDirect agents from issue to mergehttps://github.com/features/ai/github-app
MCP RegistryNewIntegrate external toolshttps://github.com/mcp
ActionsAutomate any workflowhttps://github.com/features/actions
CodespacesInstant dev environmentshttps://github.com/features/codespaces
IssuesPlan and track workhttps://github.com/features/issues
Code ReviewManage code changeshttps://github.com/features/code-review
GitHub Advanced SecurityFind and fix vulnerabilitieshttps://github.com/security/advanced-security
Code securitySecure your code as you buildhttps://github.com/security/advanced-security/code-security
Secret protectionStop leaks before they starthttps://github.com/security/advanced-security/secret-protection
Why GitHubhttps://github.com/why-github
Documentationhttps://docs.github.com
Bloghttps://github.blog
Changeloghttps://github.blog/changelog
Marketplacehttps://github.com/marketplace
View all featureshttps://github.com/features
Enterpriseshttps://github.com/enterprise
Small and medium teamshttps://github.com/team
Startupshttps://github.com/enterprise/startups
Nonprofitshttps://github.com/solutions/industry/nonprofits
App Modernizationhttps://github.com/solutions/use-case/app-modernization
DevSecOpshttps://github.com/solutions/use-case/devsecops
DevOpshttps://github.com/solutions/use-case/devops
CI/CDhttps://github.com/solutions/use-case/ci-cd
View all use caseshttps://github.com/solutions/use-case
Healthcarehttps://github.com/solutions/industry/healthcare
Financial serviceshttps://github.com/solutions/industry/financial-services
Manufacturinghttps://github.com/solutions/industry/manufacturing
Governmenthttps://github.com/solutions/industry/government
View all industrieshttps://github.com/solutions/industry
View all solutionshttps://github.com/solutions
AIhttps://github.com/resources/articles?topic=ai
Software Developmenthttps://github.com/resources/articles?topic=software-development
DevOpshttps://github.com/resources/articles?topic=devops
Securityhttps://github.com/resources/articles?topic=security
View all topicshttps://github.com/resources/articles
Customer storieshttps://github.com/customer-stories
Events & webinarshttps://github.com/resources/events
Ebooks & reportshttps://github.com/resources/whitepapers
Business insightshttps://github.com/solutions/executive-insights
GitHub Skillshttps://skills.github.com
Documentationhttps://docs.github.com
Customer supporthttps://support.github.com
Community forumhttps://github.com/orgs/community/discussions
Trust centerhttps://github.com/trust-center
Partnershttps://github.com/partners
View all resourceshttps://github.com/resources
GitHub SponsorsFund open source developershttps://github.com/open-source/sponsors
Security Labhttps://securitylab.github.com
Maintainer Communityhttps://maintainers.github.com
Acceleratorhttps://github.com/open-source/accelerator
GitHub Starshttps://stars.github.com
Archive Programhttps://archiveprogram.github.com
Topicshttps://github.com/topics
Trendinghttps://github.com/trending
Collectionshttps://github.com/collections
Enterprise platformAI-powered developer platformhttps://github.com/enterprise
GitHub Advanced SecurityEnterprise-grade security featureshttps://github.com/security/advanced-security
Copilot for BusinessEnterprise-grade AI featureshttps://github.com/features/copilot/copilot-business
Premium SupportEnterprise-grade 24/7 supporthttps://github.com/enterprise/premium-support
Pricinghttps://github.com/pricing
Search syntax tipshttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
documentationhttps://docs.github.com/search-github/github-code-search/understanding-github-code-search-syntax
Sign in https://github.com/login?return_to=https%3A%2F%2Fgithub.com%2FHankCoder%2FBlogAndCode%2Fissues%2F11
Sign up https://github.com/signup?ref_cta=Sign+up&ref_loc=header+logged+out&ref_page=%2F%3Cuser-name%3E%2F%3Crepo-name%3E%2Fvoltron%2Fissues_fragments%2Fissue_layout&source=header-repo&source_repo=HankCoder%2FBlogAndCode
Reloadhttps://github.com/HankCoder/BlogAndCode/issues/11
Reloadhttps://github.com/HankCoder/BlogAndCode/issues/11
Reloadhttps://github.com/HankCoder/BlogAndCode/issues/11
HankCoder https://github.com/HankCoder
BlogAndCodehttps://github.com/HankCoder/BlogAndCode
Notifications https://github.com/login?return_to=%2FHankCoder%2FBlogAndCode
Fork 0 https://github.com/login?return_to=%2FHankCoder%2FBlogAndCode
Star 1 https://github.com/login?return_to=%2FHankCoder%2FBlogAndCode
Code https://github.com/HankCoder/BlogAndCode
Issues 16 https://github.com/HankCoder/BlogAndCode/issues
Pull requests 0 https://github.com/HankCoder/BlogAndCode/pulls
Actions https://github.com/HankCoder/BlogAndCode/actions
Projects https://github.com/HankCoder/BlogAndCode/projects
Security and quality 0 https://github.com/HankCoder/BlogAndCode/security
Insights https://github.com/HankCoder/BlogAndCode/pulse
Code https://github.com/HankCoder/BlogAndCode
Issues https://github.com/HankCoder/BlogAndCode/issues
Pull requests https://github.com/HankCoder/BlogAndCode/pulls
Actions https://github.com/HankCoder/BlogAndCode/actions
Projects https://github.com/HankCoder/BlogAndCode/projects
Security and quality https://github.com/HankCoder/BlogAndCode/security
Insights https://github.com/HankCoder/BlogAndCode/pulse
Android Touch事件分发机制系列一基本流程梳理https://github.com/HankCoder/BlogAndCode/issues/11#top
Androidhttps://github.com/HankCoder/BlogAndCode/issues?q=state%3Aopen%20label%3A%22Android%22
https://github.com/HankCoder
HankCoderhttps://github.com/HankCoder
on Oct 20, 2017https://github.com/HankCoder/BlogAndCode/issues/11#issue-267059131
https://user-images.githubusercontent.com/28669743/31529718-91cf1884-afa0-11e7-845d-8cf174fba496.png
Androidhttps://github.com/HankCoder/BlogAndCode/issues?q=state%3Aopen%20label%3A%22Android%22
https://github.com
Termshttps://docs.github.com/site-policy/github-terms/github-terms-of-service
Privacyhttps://docs.github.com/site-policy/privacy-policies/github-privacy-statement
Securityhttps://github.com/security
Statushttps://www.githubstatus.com/
Communityhttps://github.community/
Docshttps://docs.github.com/
Contacthttps://support.github.com?tags=dotcom-footer

Viewport: width=device-width


URLs of crawlers that visited me.