【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 四 | View 事件传递机制 )(一)

简介: 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 四 | View 事件传递机制 )(一)

文章目录

Android 事件分发 系列文章目录

前言

一、View 的事件传递机制 ( dispatchTouchEvent )

二、触摸事件 与 点击事件 冲突处理

三、View 事件分发相关源码

前言

接上一篇博客 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 三 ) , 继续分析 ViewGroup 的事件分发机制后续代码 ;






一、View 的事件传递机制 ( dispatchTouchEvent )


在上一篇博客 【Android 事件分发】事件分发源码分析 ( ViewGroup 事件传递机制 三 ) 二、当前遍历的子组件的事件分发 章节 , 分析到 ViewGroup 的 dispatchTouchEvent 方法中的最终事件分发 , 调用到了 View 的 dispatchTouchEvent 方法继续向子组件分发触摸事件 ;


View 组件设置 点击监听器 View.OnClickListener , 触摸监听器 View.OnTouchListener , 都设置在 View 的 View.ListenerInfo 类型成员中 ;


判断该组件是否被用户设置了 触摸监听器 OnTouchListener , 如果设置了 , 则执行被用户设置的 触摸监听器 OnTouchListener ;

如果用户设置的 触摸监听器 OnTouchListener 触摸方法返回 true , 此时该分发方法的返回值就是 true ;


public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
    public boolean dispatchTouchEvent(MotionEvent event) {
            //noinspection SimplifiableIfStatement
            // 设置的 触摸监听器 就是封装在该对象中 
            ListenerInfo li = mListenerInfo;
            // 判断该组件是否被用户设置了 触摸监听器 OnTouchListener
            if (li != null && li.mOnTouchListener != null
                    && (mViewFlags & ENABLED_MASK) == ENABLED
                    // 执行被用户设置的 触摸监听器 OnTouchListener
                    && li.mOnTouchListener.onTouch(this, event)) {
                // 如果用户设置的 触摸监听器 OnTouchListener 触摸方法返回 true
                // 此时该分发方法的返回值就是 true 
                result = true;
            }
  }
}


如果上述 li.mOnTouchListener.onTouch(this, event) 执行的触摸监听器触摸方法返回值为 true , 则不会调用 View 组件自己的 onTouchEvent 方法了 , 在 onTouchEvent 方法中会调用 点击监听器的方法 ;

如果用户的 触摸监听器 OnTouchListener 返回 true , 则 用户的 点击监听器 OnClickListener 会被屏蔽掉 ;

如果同时设置了 点击监听器 OnClickListener 和 触摸监听器 OnTouchListener , 此时需要做 触摸事件 与 点击事件的兼容处理 ;


public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
    public boolean dispatchTouchEvent(MotionEvent event) {
    // 如果上面为 true ( 触摸监听器的触摸事件处理返回 true ) , 就会阻断该分支的命中 , 该分支不执行了 
    // 也就不会调用 View 组件自己的 onTouchEvent 方法 
    // 因此 , 如果用户的 触摸监听器 OnTouchListener 返回 true 
    // 则 用户的 点击监听器 OnClickListener 会被屏蔽掉 
    // 如果同时设置了 点击监听器 OnClickListener 和 触摸监听器 OnTouchListener 
    // 触摸监听器 OnTouchListener 返回 false , 点击监听器 OnClickListener 才能被调用到 
            if (!result && onTouchEvent(event)) {
                result = true;
            }
  }
}



View 的 onTouchEvent 方法分析 :


Click 点击事件 , 是一次完整的按下 + 抬起操作 , 如果要判定点击 , 需要同时有 MotionEvent.ACTION_DOWN + MotionEvent.ACTION_UP 事件 , 因此这里在 MotionEvent.ACTION_UP 事件分支中查找点击事件 ;


最终找到了点击事件的调用方法 performClickInternal 方法 ;


public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
    public boolean onTouchEvent(MotionEvent event) {
        if (clickable || (viewFlags & TOOLTIP) == TOOLTIP) {
            switch (action) {
                case MotionEvent.ACTION_UP:
                  // 点击事件 Click 是 按下 + 抬起 事件 
                  // 如果要判定点击 , 需要同时有 MotionEvent.ACTION_DOWN + MotionEvent.ACTION_UP 事件 
                        if (!mHasPerformedLongPress && !mIgnoreNextUpEvent) {
                            // This is a tap, so remove the longpress check
                            removeLongPressCallback();
                            // Only perform take click actions if we were in the pressed state
                            if (!focusTaken) {
                                // Use a Runnable and post this rather than calling
                                // performClick directly. This lets other visual state
                                // of the view update before click actions start.
                                if (mPerformClick == null) {
                                  // 此处创建点击对象 
                                    mPerformClick = new PerformClick();
                                }
                                // 调用点击事件 
                                if (!post(mPerformClick)) {
                                    performClickInternal();
                                }
                            }
                        }
  }
}



在 performClickInternal 方法中, 调用了 performClick 方法 ;


public class View implements Drawable.Callback, KeyEvent.Callback,
        AccessibilityEventSource {
    private boolean performClickInternal() {
        // Must notify autofill manager before performing the click actions to avoid scenarios where
        // the app has a click listener that changes the state of views the autofill service might
        // be interested on.
        notifyAutofillManagerOnClick();
        return performClick();
    }
}


目录
相关文章
|
2月前
|
存储 安全 Android开发
探索Android与iOS的隐私保护机制
在数字化时代,移动设备已成为我们生活的一部分,而隐私安全是用户最为关注的问题之一。本文将深入探讨Android和iOS两大主流操作系统在隐私保护方面的策略和实现方式,分析它们各自的优势和不足,以及如何更好地保护用户的隐私。
|
2月前
|
Linux Android开发 iOS开发
深入探索Android与iOS的多任务处理机制
在移动操作系统领域,Android和iOS各有千秋,尤其在多任务处理上展现出不同的设计理念和技术实现。本文将深入剖析两大平台在后台管理、资源分配及用户体验方面的策略差异,揭示它们如何平衡性能与电池寿命,为用户带来流畅而高效的操作体验。通过对比分析,我们不仅能够更好地理解各自系统的工作机制,还能为开发者优化应用提供参考。
|
2月前
|
算法 Linux 调度
深入探索安卓系统的多任务处理机制
【10月更文挑战第21天】 本文旨在为读者提供一个关于Android系统多任务处理机制的全面解析。我们将从Android操作系统的核心架构出发,探讨其如何管理多个应用程序的同时运行,包括进程调度、内存管理和电量优化等方面。通过深入分析,本文揭示了Android在处理多任务时所面临的挑战以及它如何通过创新的解决方案来提高用户体验和设备性能。
75 1
|
2月前
|
XML 前端开发 Android开发
Android:UI:Drawable:View/ImageView与Drawable
通过本文的介绍,我们详细探讨了Android中Drawable、View和ImageView的使用方法及其相互关系。Drawable作为图像和图形的抽象表示,提供了丰富的子类和自定义能力,使得开发者能够灵活地实现各种UI效果。View和ImageView则通过使用Drawable实现了各种图像和图形的显示需求。希望本文能为您在Android开发中使用Drawable提供有价值的参考和指导。
53 2
|
2月前
|
Android开发 开发者 UED
安卓开发中自定义View的实现与性能优化
【10月更文挑战第28天】在安卓开发领域,自定义View是提升应用界面独特性和用户体验的重要手段。本文将深入探讨如何高效地创建和管理自定义View,以及如何通过代码和性能调优来确保流畅的交互体验。我们将一起学习自定义View的生命周期、绘图基础和事件处理,进而探索内存和布局优化技巧,最终实现既美观又高效的安卓界面。
53 5
|
3月前
|
缓存 数据处理 Android开发
在 Android 中使用 RxJava 更新 View
【10月更文挑战第20天】使用 RxJava 来更新 View 可以提供更优雅、更高效的解决方案。通过合理地运用操作符和订阅机制,我们能够轻松地处理异步数据并在主线程中进行 View 的更新。在实际应用中,需要根据具体情况进行灵活运用,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在 Android 中使用 RxJava 更新 View 的技巧和方法,为开发高质量的 Android 应用提供有力支持。
|
3月前
|
缓存 调度 Android开发
Android 在子线程更新 View
【10月更文挑战第21天】在 Android 开发中,虽然不能直接在子线程更新 View,但通过使用 Handler、AsyncTask 或 RxJava 等方法,可以实现子线程操作并在主线程更新 View 的目的。在实际应用中,需要根据具体情况选择合适的方法,并注意相关的注意事项和性能优化,以确保应用的稳定性和流畅性。可以通过不断的实践和探索,进一步掌握在子线程更新 View 的技巧和方法,为开发高质量的 Android 应用提供支持。
58 2
|
3月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
Android面试高频知识点(3) 详解Android View的绘制流程
|
4天前
|
缓存 前端开发 Android开发
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程
【04】flutter补打包流程的签名过程-APP安卓调试配置-结构化项目目录-完善注册相关页面-开发完整的社交APP-前端客户端开发+数据联调|以优雅草商业项目为例做开发-flutter开发-全流程

热门文章

最新文章