【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();
    }
}


目录
相关文章
|
10天前
|
缓存 搜索推荐 Android开发
安卓应用开发中的自定义View组件实践
【9月更文挑战第10天】在安卓开发领域,自定义View是提升用户体验和实现界面个性化的重要手段。本文将通过一个实际案例,展示如何在安卓项目中创建和使用自定义View组件,包括设计思路、实现步骤以及可能遇到的问题和解决方案。文章不仅提供了代码示例,还深入探讨了自定义View的性能优化技巧,旨在帮助开发者更好地掌握这一技能。
|
12天前
|
Android开发
Android中SurfaceView的双缓冲机制和普通View叠加问题解决办法
本文介绍了 Android 平台上的 SurfaceView,这是一种高效的图形渲染控件,尤其适用于视频播放、游戏和图形动画等场景。文章详细解释了其双缓冲机制,该机制通过前后缓冲区交换来减少图像闪烁,提升视觉体验。然而,SurfaceView 与普通 View 叠加时可能存在 Z-Order 不一致、同步问题及混合渲染难题。文中提供了使用 TextureView、调整 Z-Order 和创建自定义组合控件等多种解决方案。
46 9
|
16天前
|
Android开发 容器
Android经典实战之如何获取View和ViewGroup的中心点
本文介绍了在Android中如何获取`View`和`ViewGroup`的中心点坐标,包括计算相对坐标和屏幕上的绝对坐标,并提供了示例代码。特别注意在视图未完成测量时可能出现的宽高为0的问题及解决方案。
25 7
|
22天前
|
XML 搜索推荐 Android开发
安卓开发中的自定义View组件实践
【8月更文挑战第30天】探索Android世界,自定义View是提升应用界面的关键。本文以简洁的语言带你了解如何创建自定义View,从基础到高级技巧,一步步打造个性化的UI组件。
|
1月前
|
API Android开发 开发者
Android经典实战之使用ViewCompat来处理View兼容性问题
本文介绍Android中的`ViewCompat`工具类,它是AndroidX库核心部分的重要兼容性组件,确保在不同Android版本间处理视图的一致性。文章列举了设置透明度、旋转、缩放、平移等功能,并提供了背景色、动画及用户交互等实用示例。通过`ViewCompat`,开发者可轻松实现跨版本视图操作,增强应用兼容性。
76 5
|
1月前
|
XML 前端开发 Android开发
Android面试高频知识点(3) 详解Android View的绘制流程
View的绘制和事件处理是两个重要的主题,上一篇《图解 Android事件分发机制》已经把事件的分发机制讲得比较详细了,这一篇是针对View的绘制,View的绘制如果你有所了解,基本分为measure、layout、draw 过程,其中比较难理解就是measure过程,所以本篇文章大幅笔地分析measure过程,相对讲得比较详细,文章也比较长,如果你对View的绘制还不是很懂,对measure过程掌握得不是很深刻,那么耐心点,看完这篇文章,相信你会有所收获的。
69 2
|
6天前
|
Android开发 开发者 Kotlin
探索安卓开发中的新特性
【9月更文挑战第14天】本文将引导你深入理解安卓开发领域的一些最新特性,并为你提供实用的代码示例。无论你是初学者还是经验丰富的开发者,这篇文章都会给你带来新的启示和灵感。让我们一起探索吧!
|
1天前
|
Android开发 开发者
安卓开发中的自定义视图:从入门到精通
【9月更文挑战第19天】在安卓开发的广阔天地中,自定义视图是一块充满魔力的土地。它不仅仅是代码的堆砌,更是艺术与科技的完美结合。通过掌握自定义视图,开发者能够打破常规,创造出独一无二的用户界面。本文将带你走进自定义视图的世界,从基础概念到实战应用,一步步展示如何用代码绘出心中的蓝图。无论你是初学者还是有经验的开发者,这篇文章都将为你打开一扇通往创意和效率的大门。让我们一起探索自定义视图的秘密,将你的应用打造成一件艺术品吧!
18 10
|
3天前
|
Java Linux Android开发
深入理解Android开发:从基础到高级
【9月更文挑战第17天】本文将深入探讨Android开发的各个方面,包括应用开发、操作系统等。我们将通过代码示例来展示如何创建一个简单的Android应用,并解释其背后的原理。无论你是初学者还是有经验的开发者,这篇文章都将为你提供有价值的信息和启示。
|
1天前
|
Java Android开发 C++
🚀Android NDK开发实战!Java与C++混合编程,打造极致性能体验!📊
在Android应用开发中,追求卓越性能是不变的主题。本文介绍如何利用Android NDK(Native Development Kit)结合Java与C++进行混合编程,提升应用性能。从环境搭建到JNI接口设计,再到实战示例,全面展示NDK的优势与应用技巧,助你打造高性能应用。通过具体案例,如计算斐波那契数列,详细讲解Java与C++的协作流程,帮助开发者掌握NDK开发精髓,实现高效计算与硬件交互。
7 1