一张图看透Android事件传递机制

本文通过图解方式深入剖析Android触屏事件的传递机制,包括事件如何从Activity传入ViewGroup,再到具体View,以及事件的回传过程。

一、引言

        总觉得知识必须要总结,不然就算再熟悉的东西,一段时间不接触就容易遗忘;上次给一个朋友解释回调的时候就有深刻的体会,所以现在养成总结的习惯,而我觉得最直观的方法就是图解,所以就有了下面的图,通过这张图看透Android事件传递机制;
        PS:有时候自己的理解可能也存在问题,所以通过这种形式能够得到大家的审查和修改意见,在这里先谢谢大家了!

二、就是这张图(自己看了一下,这张图看不清楚,复制或保存本地,使用图片查看器放大查看;或者点击链接查看原图)


三、图片局部细节详解

1.Touch事件的传入  :


            
            开始由UserActivity(用户自定义的Activity)接收到事件,这个类继承自Activity,没有 onInterceptTouchEvent方法(为什么没有?谁能给我一个合理的解释吗?)
事件传递到 disPatchTouchEvent,这里默认的是调用父类的disPatchTouchEvent,查看父类的源码可以看到,
    /**
     * Called to process touch screen events.  You can override this to
     * intercept all touch screen events before they are dispatched to the
     * window.  Be sure to call this implementation for touch screen events
     * that should be handled normally.
     * 
     * @param ev The touch screen event.
     * 
     * @return boolean Return true if this event was consumed.
     */
    public boolean dispatchTouchEvent(MotionEvent ev) {
        if (ev.getAction() == MotionEvent.ACTION_DOWN) {
            onUserInteraction();
        }
        if (getWindow().superDispatchTouchEvent(ev)) {
            return true;
        }
        return onTouchEvent(ev);
    }

            这里的第一个判断条件中方法的执行为为空实现:

            第二个判断中的判断条件是有窗体事件分配决定的,窗体默认的事件分发机制,再往里面看,如下代码
    /**
     * Used by custom windows, such as Dialog, to pass the touch screen event
     * further down the view hierarchy. Application developers should
     * not need to implement or call this.
     *
     */
    public abstract boolean superDispatchTouchEvent(MotionEvent event);
    
               可以理解为Android系统自己定义的事件分发机制,上面说明了应用开发者不需要去实现或者调用这个方法。我理解的是系统已经为你准备好了普通窗口事件该如何分发,不需要你再手动去修改这块代码了!如果你不按照我的方法来做,那么好吧,后面的事你都自己干吧,就是这么任性。所以在UserActivity中手动修改dispatchTouchEvent方法的返回值,就会使本次事件被消费掉,不再向里层传递。
顺带看看onTouchEvent方法吧:
    /**
     * Called when a touch screen event was not handled by any of the views
     * under it.  This is most useful to process touch events that happen
     * outside of your window bounds, where there is no view to receive it.
     * 
     * @param event The touch screen event being processed.
     * 
     * @return Return true if you have consumed the event, false if you haven't.
     * The default implementation always returns false.
     */
    public boolean onTouchEvent(MotionEvent event) {
        if (mWindow.shouldCloseOnTouch(this, event)) {
            finish();
            return true;
        }
        
        return false;
    }

          从上面的说明可以看出,当触屏事件没有被内层所有的view处理的时候才会被调用;当处理你窗体外没有任何view处理的Touch事件的时候最有用。
          从返回值说明可以看出,默认返回值通常为false,所以一般如果事件不被子view消费,事件一般都会被舍弃掉


2.从Activity中传入外层的ViewGroup中


                经过了UserActivty后传入到ViewParent中来,第一个走的肯定还是dispatchTouchEvent,依然,如果手动修改dispathTouchEvent的返回值,本次事件就到此为止。如果使用父类(ViewGroup)的事件分发机制,那么事件就会首先传递到onInterceptToucEvent中来;(这部分里面代码太多,我想你也没兴趣看;万一你是个Geek,那你也可以自己去扒一扒源码,自己阅读一下,这里就不再详细介绍了,本文就是为了言简意赅的说明Touch事件的传递机制,所以见谅)
在onInterceptTouchEvent中,就会询问你“你想不想拦截本次事件啊?”
|--“想”(return true),那么事件就会进入自己的onTouchEvent中执行
        那么事件就会到了onTouchEvent中,这时系统就会问你:“你想不想处理这次点击事件啊?”
            |--“想”(return true)那么本次事件被消费掉了
            |--“不想”(return false)那么他就会认为你里层的子控件都不想接收本次事件,那他直接把本次事件往回传递(传回UserActivty中去处理)。需要注意的是,如果 本次事 件是DOWN事件,那么本次的MOVE、UP也将不会传递到ViewParent中来了,注意是本次哦,仅仅只是指你一次按下到抬起这一套动作,还有第二 次,第三次,还是要来的。
            |--"你自己说了算,按照你的想法去做吧!"(return super.onTouchEvent(ev);)那就要交给ViewParent的父类去决定了,不过一般ViewGruop中都不会去处理事 件,即一 般返回false
|--“不想”(return false),既然你不想拦截,那我就去问问你里面的人想不想处理吧,事件就会向里层传递,即下面的ViewChild
|--“你自己说了算,按照你的想法去做吧!”(return super.onTouchEvent(ev);),系统当然是想有人来消费这个事件了,既然你让我自己决定,那我也想向你里面的子控件 问问啊!

3.事件传递到了ViewChild中


这里当然是最里层控件了.
        dipatchTouchEvent:还是和上面的一样,还是决定是否分发事件,系统的逻辑会自动运行到自己onTouchEvent方法中,如果你主动干预,决定是否分发(手动更改返回值),事件到这里就会终结
       onInterceptTouchEvent:最里层控件没有这个方法,既然是最里层的控件,自然就不需要询问你是否需要拦截这个事件了,因为你拦不拦截,事件到这里就算是走到了路的尽 头(之所以称为路的尽头,是因为还可以走走回头路的,哈哈!)所以这里没有啊onInterceptTouchEvent方法
        onTouchevent:逻辑和之前的一样,问你是否消费本次事件,
               |-- return true消费掉本次事件,事件结束;
               |-- return false不消费,本次事件回传到外一层控件,同样,如果是一次DOWN事件,本次的MOVE和UP将不会再传递到这里;
               |-- return super.onTouchEvent(event) 是否消费本次事件就要看自己控件类型了,我的例子中是TextView类型,就是不消费的;

4.事件回传

         事件回传,差不多是同一种情况,就是当前控件中的onTouchEvent返回值为false(默认的super.onTouchEvent方法一般也是返回false),可以理解为:
                   |-- return false:事件都交到你手里了,而且你明确说了你不要,那我只能往回传了;
                   |-- return super.onTouchEvent(event):如果你不告诉我你要不要处理,我只能默认你不处理,也就往上一层传递了
        当到达了最顶层,我的Demo程序中是MainActivity,默认不处理onTouchEvent,所以如果回传到顶层,事件会调用Activity中的onTouchEvent

本次分析到这里就算结束了,感觉有些地方的理解还存在问题,欢迎各位大神指点,先谢过了!

本次使用的图片资源和源代码,如需要,请自行下载:
链接: http://pan.baidu.com/s/1kTH59sj 密码:1m5n





【EI复现】基于深度强化学习的微能源网能量管理与优化策略研究(Python代码实现)内容概要:本文围绕“基于深度强化学习的微能源网能量管理与优化策略”展开研究,重点利用深度Q网络(DQN)等深度强化学习算法对微能源网中的能量调度进行建模与优化,旨在应对可再生能源出力波动、负荷变化及运行成本等问题。文中结合Python代码实现,构建了包含光伏、储能、负荷等元素的微能源网模型,通过强化学习智能体动态决策能量分配策略,实现经济性、稳定性和能效的多重优化目标,并可能与其他优化算法进行对比分析以验证有效性。研究属于电力系统与人工智能交叉领域,具有较强的工程应用背景和学术参考价值。; 适合人群:具备一定Python编程基础和机器学习基础知识,从事电力系统、能源互联网、智能优化等相关方向的研究生、科研人员及工程技术人员。; 使用场景及目标:①学习如何将深度强化学习应用于微能源网的能量管理;②掌握DQN等算法在实际能源系统调度中的建模与实现方法;③为相关课题研究或项目开发提供代码参考和技术思路。; 阅读建议:建议读者结合提供的Python代码进行实践操作,理解环境建模、状态空间、动作空间及奖励函数的设计逻辑,同时可扩展学习其他强化学习算法在能源系统中的应用。
<think>我们开始分析用户意:用户想知道在手机上如何查看片的内容或分析片信息。这包括识别片中的物体、文字、场景等,或者获取片的元数据(如拍摄时间、地点等)。 搜索关键词:手机 查看片内容 分析片信息 工具 方法 我们进行网络搜索,可能得到以下信息: 1. 使用手机自带的片查看器或相册应用:通常可以查看基本的元数据(如拍摄时间、设备、地理位置等)。 2. 使用专门的片分析工具或应用:如Google Lens、百度识等,可以识别物体、文字、二维码等。 3. 使用OCR(光学字符识别)应用:提取片中的文字。 4. 使用照片编辑应用:一些编辑应用提供片信息查看功能。 5. 使用文件管理器:查看片文件属性。 整合信息,生成答案: 注意:避免使用第一人称,避免步骤词汇,将答案组织为多个方法,每个方法间换行。 答案结构: 方法1:使用手机相册应用查看片信息(元数据)。 方法2:使用智能识别工具(如Google Lens)分析片内容(物体、文字等)。 方法3:使用OCR应用提取片中的文字。 方法4:通过文件管理器查看片属性。 另外,如果需要代码示例(例如使用OCR库),则按照格式要求提供。 最后,生成相关问题。 注意:我们不需要在回答中引用来源,但需要整合信息。</think>根据用户意,手机查看片内容或分析片信息可通过以下方法实现: ### 基础片信息查看 手机相册应用通常支持基础信息查看 打开片后点击"详情"或"信息"标 显示拍摄时间、设备型号、分辨率、文件大小等元数据 部分机型可查看GPS地理位置(需拍摄时开启定位) ### 智能片识别分析 安装专用识别工具如Google Lens或百度识 启动应用对准片或选择相册片 自动识别中物体、植物、动物、地标等 提供相关百科信息和购物链接 支持实时翻译片中的外文文字 ```python # 使用Pytesseract OCR示例(需安装依赖) import pytesseract from PIL import Image text = pytesseract.image_to_string(Image.open('image.jpg')) print("识别文字:", text) ``` ### 专业元数据分析 使用EXIF Viewer类应用(如Exif Metadata) 深度解析片隐藏的EXIF数据 显示光圈$f/$、快门速度$\frac{1}{t}$、ISO值等参数 支持地定位拍摄坐标$(\phi,\lambda)$ 可编辑或删除敏感元数据 ### 文字提取方案 通过OCR应用(Text Scanner, Adobe Scan) 自动识别片中的印刷/手写文字 支持导出为可编辑文本格式 具备表格识别和PDF转换功能 适合文档扫描和名片信息提取 ### 二维码/条形码解析 手机相机直接扫描二维码 或使用专用扫码工具(QR Code Reader) 自动解析网址、联系方式、WiFi密码等信息 支持生成历史记录和批量处理
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值