从源码说说dispatchTouchEvent与onTouchEvent的关系以及OnTouchListener的用法

为什么要说这个问题呢,这段时间还是在SeekBar上遇到一些问题,好像ADT并没有给seekBar在xml中提供enabled属性,虽然我们可以在代码中设置,但是它并不能实现下面这个需求,所以我们需要找到别的方式去实现它,也为了能更好的了解一下dispatchTouchEvent与onTouchEvent之间的关系。

我们现在有这么一个问题,我们需要使SeekBar在某些时候只可点击不可拖动,如果简简单单使用enabled的话,那么只会不能移动,这是不满足的。所以我们需要有这么一个入口去逐步解决这个问题。

入口点:

需要知道seekbar是如何拖动与绘制的。

首先会想到去哪找这个问题?肯定是SeekBar的onTouchEvent方法对不对?我们在拖拽seekBar的thumb的时候,肯定会触发MotionEvent.ACTION_MOVE的事件,这样一来,我们就找到了我们问题当然入口处,只用合理控制onTouchEvent方法的调用就可以了,我们从源码开始看:

在SeekBar类中是没有onTouchEvent方法的,那么我们需要去它的父类中找,如果父类中没有,那么就需要去父类的父类中去找,直到找到为止,那么我们很快的就在SeekBar的父类AbsSeekBar中找到了onTouchEvent方法:

    public boolean onTouchEvent(MotionEvent event) {if (!mIsUserSeekable || !isEnabled()) {return false;}switch (event.getAction()) {case MotionEvent.ACTION_DOWN:if (isInScrollingContainer()) {mTouchDownX = event.getX();} else {setPressed(true);if (mThumb != null) {invalidate(mThumb.getBounds()); // This may be within the padding region}onStartTrackingTouch();trackTouchEvent(event);attemptClaimDrag();}break;case MotionEvent.ACTION_MOVE:if (mIsDragging) {trackTouchEvent(event);} else {final float x = event.getX();if (Math.abs(x - mTouchDownX) > mScaledTouchSlop) {setPressed(true);if (mThumb != null) {invalidate(mThumb.getBounds()); // This may be within the padding region}onStartTrackingTouch();trackTouchEvent(event);attemptClaimDrag();}}break;case MotionEvent.ACTION_UP:if (mIsDragging) {trackTouchEvent(event);onStopTrackingTouch();setPressed(false);} else {// Touch up when we never crossed the touch slop threshold should// be interpreted as a tap-seek to that location.onStartTrackingTouch();trackTouchEvent(event);onStopTrackingTouch();}// ProgressBar doesn't know to repaint the thumb drawable// in its inactive state when the touch stops (because the// value has not apparently changed)invalidate();break;case MotionEvent.ACTION_CANCEL:if (mIsDragging) {onStopTrackingTouch();setPressed(false);}invalidate(); // see above explanationbreak;}return true;}

来分析下这段代码:

mIsUserSeekable在AbsSeekBar中声明为了true,后面也没有任何地方对它进行修改。isEnabled由于没有对它进行专门设置,所以这里恒为true。所以if中的判断恒为false。接着往下MotionEvent.ACTION_DOWN中的if(isInScrollingContainer())表示是说如果是在可以滚动的容器当中,我们这里使用的是平常的布局,所以这里为false。

setPressed(true)更改按压状态,invalidate(mThumb.getBounds())绘制thumb,onStartTrackingTouch设置mIsDragging为true为ACTION_MOVE做准备,trackTouchEvent对内部进行测量计算绘制界面,attemptClaimDrag禁止父布局及祖先布局阻断touch事件。好,接下来就是MotionEvent.ACTION_MOVE了,已知mIsDragging是true,所以当执行move的时候一直是在调用trackTouchEvent方法了,所以,我们在拖拽的seekBar的thumb的时候就是在这里进行的处理。好,有些扯远了,回到我们的主要部分:

我们刚刚可以看到onTouchEvent中没有任何一处可以对我们的触摸事件进行拦截,那我们就需要找在哪里调用了onTouchEvent方法,我们从SeekBar到其父类AbsSeekBar再到ProgressBar,最后到View的dispatchTouchEvent中被调用了:

    /*** Pass the touch screen motion event down to the target view, or this* view if it is the target.** @param event The motion event to be dispatched.* @return True if the event was handled by the view, false otherwise.*/public boolean dispatchTouchEvent(MotionEvent event) {boolean result = false;if (mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onTouchEvent(event, 0);}final int actionMasked = event.getActionMasked();if (actionMasked == MotionEvent.ACTION_DOWN) {// Defensive cleanup for new gesturestopNestedScroll();}if (onFilterTouchEventForSecurity(event)) {//noinspection SimplifiableIfStatementListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {result = true;}if (!result && onTouchEvent(event)) {result = true;}}if (!result && mInputEventConsistencyVerifier != null) {mInputEventConsistencyVerifier.onUnhandledEvent(event, 0);}// Clean up after nested scrolls if this is the end of a gesture;// also cancel it if we tried an ACTION_DOWN but we didn't want the rest// of the gesture.if (actionMasked == MotionEvent.ACTION_UP ||actionMasked == MotionEvent.ACTION_CANCEL ||(actionMasked == MotionEvent.ACTION_DOWN && !result)) {stopNestedScroll();}return result;}
我们先不管其它,只关心我们关心的:

        if (onFilterTouchEventForSecurity(event)) {//noinspection SimplifiableIfStatementListenerInfo li = mListenerInfo;if (li != null && li.mOnTouchListener != null&& (mViewFlags & ENABLED_MASK) == ENABLED&& li.mOnTouchListener.onTouch(this, event)) {result = true;}if (!result && onTouchEvent(event)) {result = true;}}

我们先不管外面那个方法,只看 内部:这里判断了li.mOnTouchListener是否为空,控件是否可用,最后通过mOnTouchListener.onTouch将事件传递进去,这里的返回值就很关键了,如果返回false,则代码会继续向下执行,最后交给onTouchEvent,如果返回true,则直接返回,不会再执行onTouchEvent方法。所以为了解决有时可以点击SeekBar,但又不能拖拽问题,我们就可以从mOnTouchListener下手了。


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/479514.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

LeetCode 617. 合并二叉树

文章目录1. 题目2. 递归解题1. 题目 给定两个二叉树,想象当你将它们中的一个覆盖到另一个上时,两个二叉树的一些节点便会重叠。 你需要将他们合并为一个新的二叉树。合并的规则是如果两个节点重叠,那么将他们的值相加作为节点合并后的新值&…

哪些 Python 库让你相见恨晚?

原文链接:https://www.zhihu.com/question/24590883/answer/92420471?utm_sourcewechat_session&utm_mediumsocial&utm_oi57646627422208&utm_contentgroup1_Answer&utm_campaignshareopn Awesome Python 中文版网站​jobbole.github.ioAwesome Py…

BIO,NIO,AIO

BIO,NIO,AIO 介绍一、背景1.1 说明1.2 通信技术整体解决的问题二、Java的I/O演进之路2.1 I/O 模型基本说明2.2 I/O模型Java BIOJava NIOJava AIO2.3 BIO、NIO、AIO 适用场景分析三、BIO,NIO,AIO总结一、背景 1.1 说明 ​ 在Java的软件设计开发中,通信架构是不可避…

学PyTorch还是TensorFlow?

在机器学习领域,面对各类复杂多变的业务问题,构建灵活易调整的模型是高阶机器学习工程师必备的工作能力。然而,许多工程师还是有一个想法上的误区,以为只要掌握了一种深度学习的框架就能走遍天下了。事实上,在机器学习…

Bifrost微前端框架及其在美团闪购中的实践

Bifrost(英 [‘bi:frɔst])原意彩虹桥,北欧神话中是连通天地的一条通道。而在漫威电影《雷神》中,Bifrost是神域——阿斯加德(Asgard)的出入口,神域的人通过它自由穿梭于“九界”(指…

设计模式之观察者模式在Listview中的应用

有时候我们会有这么一个需求,在Listview的某个Item上有个按钮,点击这个按钮之后呢,需要对其它的item做一些操作,就像下面这个: 采纳按钮点击之前:采纳按钮点击之后: 简单介绍一下这两张图的意…

新书速递 | 《知识图谱:方法、实践与应用》

本文转载自公众号:博文视点Broadview 。互联网促成了大数据的集聚,大数据进而促进了人工智能算法的进步。近年来知识图谱作为AI领域底层技术被越来越多的人谈起。知识图谱的升温得益于新数据和新算法为规模化知识图谱构建提供了新的技术基础和发展条件&a…

Github Star过万的阿里学长独家干货分享

浅梦是我认识的一位浙大计算机系的学长,目前在阿里从事算法相关的工作。无论在学校还是工作中,他都保持着对新知识的学习和分享。他的github star 1w,世界排名700,参与开发的项目下载量接近30w次。主要涉及「推荐系统」&#xff0…

pytorch 和 tensorflow2.0 方法替换

Embedding初始化 pytorch: Embedding() tf2.0: random.normal() # 验证均值和方差 def confirm(weight):mean np.sum(weight) / dimprint("均值: {}".format(mean))square_sum np.sum((mean - weight) ** 2)print("方差: {}".format(square_sum / dim)…

React Native在美团外卖客户端的实践

MRN简介 MRN(Meituan React Native) 是基于开源的React Native框架改造并完善而成的一套动态化方案,在开发体验上基本能与原生RN保持一致,同时从业务需求的角度满足从开发、构建、测试、部署、运维的工程化需要。解决了一系列痛点…

论文浅尝 | 使用预训练深度模型和迁移学习方法的端到端模糊实体匹配

论文笔记整理:高凤宁,南京大学硕士,研究方向为知识图谱、实体消解。链接:https://doi.org/10.1145/3308558.3313578动机目前实体匹配过程中实体之间的差异比较微妙,不同的情况下可能会有不同的决策结果,导致…

推荐几个Android开发非常有用的工具(for android studio)

原文地址: http://stormzhang.com/android/2015/05/26/android-tools/ 一晃好久没更新博客了,最近一个月真的很忙,因为公司在准备C轮融资,公司的发展到了一个关键的阶段,自己全部精力投入在公司产品上,这个状态可能还会…

分布式机器学习(下)-联邦学习

原文链接:https://zhuanlan.zhihu.com/p/114028503 本视频来源于Shusen Wang讲解的《分布式机器学习》,总共有三讲,内容和连接如下:并行计算与机器学习(上)并行计算与机器学习(下)联…

LeetCode 8. 字符串转换整数 (atoi)

文章目录1. 题目2. 解题1. 题目 示例 1: 输入: "42" 输出: 42示例 2: 输入: " -42" 输出: -42 解释: 第一个非空白字符为 -, 它是一个负号。我们尽可能将负号与后面所有连续出现的数字组合起来,最后得到 -42 。示例 3: 输入: "4193 w…

怎样将Embedding融入传统机器学习框架?

文 | 石塔西源 | 知乎LR本身是一个经典的CTR模型,广泛应用于推荐/广告系统。输入的特征大多数是离散型/组合型。那么对于Embedding技术,如何在不使用深度学习模型的情况下(假设就是不能用DNN),融入到LR框架中呢&#x…

推荐系统中的Embedding

推荐系统之Embedding一、什么是embedding?1. 让embedding空前流行的word2vec:2. 从word2vec到item2vec二、Graph Embedding1. 经典的Graph Embedding方法 — DeepWalk2. DeepWalk改进 — Node2vec3. 阿里的Graph Embedding方法EGES三、深度学习推荐系统中…

美团下一代服务治理系统 OCTO 2.0 的探索与实践

本文根据美团基础架构部服务治理团队工程师郭继东在2019 QCon(全球软件开发大会)上的演讲内容整理而成,主要阐述美团大规模治理体系结合 Service Mesh 演进的探索实践,希望对从事此领域的同学有所帮助。 一、OCTO 现状分析 OCTO 是…

技术动态 | 跨句多元关系抽取

本文转载自公众号&#xff1a;知识工场。第一部分 概述关系抽取简介关系抽取是从自由文本中获取实体间所具有的语义关系。这种语义关系常以三元组 <E1,R,E2> 的形式表达&#xff0c;其中&#xff0c;E1 和E2 表示实体&#xff0c;R 表示实体间所具有的语义关系。如图1所示…

JAVA1.6实现动态编译加载运行

一直以为我们写好的程序都需要预先编译好&#xff0c;然后再运行&#xff0c;直到今天在看书的时候才看到书上说JAVA1.6之后可以动态的编译JAVA文件&#xff0c;这着实让我高兴了一把&#xff0c;为什么这么兴奋呢&#xff0c;我一心想着能用技术实现动态更新APK&#xff0c;不…

网络解析(一):LeNet-5详解

原文链接&#xff1a;https://cuijiahua.com/blog/2018/01/dl_3.html 2018年1月9日21:03:313994,282 C摘要LeNet-5出自论文Gradient-Based Learning Applied to Document Recognition&#xff0c;是一种用于手写体字符识别的非常高效的卷积神经网络。一、前言LeNet-5出自论文Gr…