[Android]视图的控触操作-MotionEvent

news2024/9/25 5:22:55

 引入

对屏幕的任何操作,系统都会创建一个触摸事件的对象MotionEvent来应对这个操作。当点击手机屏幕的某一个视图时,最先感应到的是屏幕,因为Activity系统是分层的结构,底层是一些驱动,所以驱动就会得到信息并且把信息传到被点击的应用,应用再交给Activity,Activity通过MotionEvent对象来实现对视图的触控操作,那么接下来我们学习一下MotionEvent对象如何实现对视图的触控操作。


一、事件的操作类型

正常情况下,一次手指触摸屏幕的行为会引起一系列的点击事件,MotionEvent对象存在变量action来反映这一系列点击事件的操作类型,所以我们可以通过MotionEvent对象的action变量的值来得到当前的点击状态。

  • 手指按下时,action的值等于ACTION_DOWN,等于0
  • 手指在屏幕上移动时,action的值等于ACTION_MOVE,等于2
  • 手指离开屏幕,action的值等于ACTION_UP,等于1

单点触控一次简单的交互流程有两种情况:

  • 手指按下,马上离开,action的值的变化为0->1
  • 手指按下,在屏幕上移动一段距离后离开屏幕,action的值的变化为0->2->...->2->1


二、MotionEvent的传递,消耗,处理过程

事件分发的三个重要方法:

       1、dispatchTouchEvent()方法:会从Activity开始一层一层地向子View分发事件,直到没有子           View。(分发的时候,只能是View分发给子View,不能View分发给孙View)

        2、onTouchEvent()方法:会在dispatchTouchEvent()方法调用到最底层View之后,再从最底           层View一层一层地往上回调,如果某个View的onTouchEvent方法返回true,那么就会停止            向上回调。

        3、onInterceptTouchEvent方法:伴随着dispatchTouchEvent()方法存在,它的作用就是拦截          ViewGroup的事件,不让它继续向下分发事件。

Activity,View,ViewGroup和MotionEvent的主要方法:

Activity:

dispatchTouchEvent(ev: MotionEvent?): Boolean分发事件
onTouchEvent(ev: MotionEvent?): Boolean处理事件的回调

View:

dispatchTouchEvent(ev: MotionEvent?): Boolean分发事件
onTouchEvent(ev: MotionEvent?): Boolean处理事件的回调
setOnTouchListener(l:OnTouchListener)设置事件监听器
setOnClickListener(l:OnClickListener)设置点击监听
setOnLongClickListener(l:OnClickListener)设置长按监听
setOnCreateContextMenuListener(l:OnCreateContextMenuListener)用于创建菜单

注意:OnTouchListener中的onTouch()事件优先级高于onTouchEvent()事件,如果onTocuh()的返回结果为ture,那么该View的onTouchEvent()事件将不会被调用。

ViewGroup:

dispatchTouchEvent(ev: MotionEvent?): Boolean分发事件
onInterceptTouchEvent(ev: MotionEvent?): Boolean
拦截事件

注意:onInterceptTouchEvent方法只在ViewGroup中可以重写。

MotionEvent:

同时通过MotionEvent对象我们可以得到点击事件的x和y轴坐标。

系统提供的方法如下:

getX()得到事件发生的x轴坐标(相对于当前视图)
getY()得到事件发生的y轴坐标(相对于当前视图)
getRawX()得到事件发生的x轴坐标(相对于屏幕左顶点)
getRawY()得到事件发生的y轴坐标(相对于屏幕左顶点)

 下面我们来理解一下MotionEvent的传递,消耗,处理过程

如图所示,当点击事件产生之后,事件首先会传递给当前的Activtiy,Activity会调用分发事件方法dispatchTouchEvent将事情传递给最大的View,然后再一层层地向下传递给子View,直到传递到最小的view,调用最小的view的onTouchEvent方法,向上传递,直到有一个view的onTouchEvent方法返回true,消耗这个点击事件,消耗这个点击事件之后就不会向上传递了。如果没有,那么事件最终会被activity消耗。

通俗点说就是:爷爷(Activity)得到了一个苹果(点击事件),爷爷把苹果给了爸爸(View),爸爸把苹果给了我(子View),如果我选择不吃苹果,那么就把苹果给爸爸,如何爸爸如果选择吃了苹果,就是把苹果消耗了,如果爸爸选择不吃苹果,就把苹果给爷爷,爷爷只能吃掉苹果,结束。

通过代码加深理解MotionEvent的传递,消耗,处理过程

当View的onTouch和onTouchEvent方法都返回false时

点击一下View,产生的点击事件如下:

点击View并移动,产生的点击事件如下:

最终都是Activity消费了点击事件。

当View的onTouch方法返回true时:

点击一下View,产生的点击事件如下:

 

 点击View并移动,产生的点击事件如下:

最终都是View消费了点击事件,并且可以看出OnTouchListener中的onTouch()事件优先级高于onTouchEvent()事件,如果onTocuh()的返回结果为ture,那么该View的onTouchEvent()事件将不会被调用。

小项目

先看效果图:

 

  • 功能描述

            通过手指移动来拖动图片

           控制图片不能超过屏幕显示区域

  • 技术点

         MotionEvent处理

         对View进行动态定位(layout)

代码:

class MainActivity : AppCompatActivity(),View.OnTouchListener{
    var lastX=0
    var lastY=0
    lateinit var imageView: ImageView
    lateinit var parentView:RelativeLayout
    var maxRight=0
    var maxBottom=0
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        imageView=findViewById(R.id.imageView4)
        parentView=imageView.parent as RelativeLayout
        imageView.setOnTouchListener(this)
    }
    override fun onTouch(p0: View?, event: MotionEvent): Boolean {
        val eventX=event.rawX
        val eventY=event.rawY
        when(event.action){
            MotionEvent.ACTION_DOWN->{
                if(maxRight==0){
                    maxRight=parentView.right
                    maxBottom=parentView.bottom
                }
                lastX= eventX.toInt()
                lastY=eventY.toInt()}
            MotionEvent.ACTION_MOVE->{
                var dx:Int=(eventX-lastX).toInt()
                var dy:Int=(eventY-lastY).toInt()
                var left=imageView.left+dx
                var top=imageView.top+dy
                var right=imageView.right+dx
                var bottom=imageView.bottom+dy
                //限制left>=0
                if(left<0){
                    right+=-left
                    left=0
                }
                //限制top>=0
                if(top<0){
                    bottom+=-top
                    top=0
                }
                //限制right<maxRight
                if(right>maxRight){
                    left-=right-maxRight
                    right=maxRight
                }
                //限制bottom>=0
                if(bottom>maxBottom){
                    top-=bottom-maxBottom
                    bottom=maxBottom
                }
                imageView.layout(left, top, right, bottom)
                lastX=eventX.toInt()
                lastY=eventY.toInt()
            }
        }
        return true
    }
}

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

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

相关文章

分布式共识算法——Paxos、ZAB、Raft

分布式算法 01 分布式基本理论 CAP理论 1998年&#xff0c;加州大学的计算机科学家 Eric Brewer 提出&#xff0c;分布式系统有三个指标。 一致性&#xff08;C&#xff09;&#xff1a;在分布式系统中的所有数据备份&#xff0c;在同一时刻是否同样的值&#xff0c;即写操…

第008课 - linux安装docker

文章目录 linux安装docker安装docker启动docker检查dockerdocker设置开机自启动linux安装docker 每一种容器都是一个完整的运行环境,容器之间互相隔离的。 windows的ghost工具就是类似docker。 从网上获取镜像,基于镜像,docker可以启动一个容器。 所以,我们以后想要装某种…

elasticsearch在linux环境安装遇到问题

es在linux环境安装遇到问题 1、启动失败日志 ERROR: [1] bootstrap checks failed [1]: the default discovery settings are unsuitable for production use; at least one of [discovery.seed_hosts, discovery.seed_providers, cluster.initial_master_nodes] must be con…

对某颜色站的一次渗透实战

1. 前提 1.1 某颜色cms弱口令原理 去年的时候&#xff0c;在网上看到有些师傅在打击颜色站&#xff0c;当时自己也摸索着试试&#xff0c;利用一个叫做jiuse cms的站来进行批量测试。 这个cms的特点是非常的小&#xff0c;前台除了xss之外&#xff0c;基本上漏洞都在后台&…

区块链+游戏:未来真的有未来吗?

今年以来&#xff0c;伴随着元宇宙与P2E的火热浪潮&#xff0c;区块链以其强大的叙事能力势如破竹的切入到传统游戏领域&#xff0c;顶级风投、知名巨企纷纷入局&#xff0c;迸发出极大的经济潜能&#xff0c;引发了社会的广泛关注。 一方面&#xff0c;区块链技术在游戏的运用…

【漏洞复现】多语言文件包含漏洞分析

漏洞描述&#xff1a; ThinkPHP在开启多语言功能的情况下存在文件包含漏洞&#xff0c;攻击者可以通过get、header、cookie等位置传入参数&#xff0c;实现目录穿越文件包含&#xff0c;通过pearcmd文件包含这个trick即可实现RCE。 影响版本&#xff1a; 6.0.1 < ThinkPH…

【TypeScript】TS交叉类型联合类型(四)

&#x1f431;个人主页&#xff1a;不叫猫先生 &#x1f64b;‍♂️作者简介&#xff1a;前端领域新星创作者、华为云享专家、阿里云专家博主&#xff0c;专注于前端各领域技术&#xff0c;共同学习共同进步&#xff0c;一起加油呀&#xff01; &#x1f4ab;系列专栏&#xff…

Mybatis_Plus_@TableName,@TableField

思考一个问题:为啥继承BaseMapper< POJO >&#xff0c;能直接找到Mysql的表 默认情况下:mp根据BaseMapper泛型POJO类取数据库底下找与POJO类型一致的表 思考一个问题:如果把表user改成tb_user那么我们需要怎么解决 使用TableName注解 TableField 思考一个问题:我们新增…

学习.NET MAUI Blazor(五)、修改窗口标题

由于Blazor属于SPA&#xff08;single-page application&#xff09;&#xff0c;所以页面标题需要使用PageTitle组件来实现。但是在MAUI Blazor中&#xff0c;Blazor所在的位置是WebView&#xff0c;而标题是属于window。所以在MAUI Blazor中&#xff0c;使用PageTitle是无效的…

vue+bpmn-js 示例/基础入门/动态创建流程节点

先附一个完整的示例&#xff0c;下面做具体介绍 <template><div classcontainers><el-button click"saveXml"></el-button><div class"canvas" ref"canvas"></div><div class"properties" id…

YOLO系列中Anchor Based和Anchor Free的相爱相杀

前言 我们都知道按照是否出现RPN可将目标检测算法分为two-stage和one-stage&#xff0c;其中one-stage的一个主要代表便是YOLO系列&#xff0c;而根据是否存在先验锚框的定义我们也可以将其分为Anchor based和Anchor free两类&#xff0c;关于这两种也是各有优劣&#xff0c;但…

物联网终端的防护体系

针对漏洞的恶意行为分析 我们共捕获到 4 种针对 UPnP 漏洞的利用行为 1&#xff0c;如表 4.7 所示。从中可以看出&#xff0c;这些漏洞均为远程 命令执行类漏洞。另外我们也发现&#xff0c;当漏洞出现在特定端口时&#xff0c;攻击者一般不会经过 UPnP 的发现阶段&#xff0c…

携手用友低代码开发,德鑫物联将RFID融入企业服务大生态

如今&#xff0c;消费者凭借一部手机就可以轻松鉴别名酒的真伪&#xff1a;一些名酒在瓶盖的封膜下已经植入了RFID芯片&#xff0c;消费者用带有NFC功能的手机并安装相应的APP&#xff0c;只需靠近RFID芯片&#xff0c;即可获取产品品名、规格、生产日期等验证信息。 不只是名…

论文阅读:人机情绪的趋同、循环与溢出——基于 Twitter 涉中议题的数据分析

论文链接&#xff1a;https://shimo.im/files/vVqRVZGEXgcZbRqy/ 《人机情绪的趋同、循环与溢出...tter涉中议题的数据分析_黄阳坤.pdf》&#xff0c;可复制链接后用石墨文档 App 打开 摘要&#xff1a; 在传播研究情感转向的背景下&#xff0c;社交媒体上人机用户间的情绪互动…

【操作系统】抖动、缺页中断率、页面置换算法

文章目录缺页中断率影响缺页中断率的因素抖动&#xff08;颠簸&#xff09;页面置换算法1、最佳页面淘汰算法&#xff08;OPT&#xff09;2、先进先出页面淘汰算法&#xff08;FIFO&#xff09;3、最近最久未使用页面淘汰算法&#xff08;LRU&#xff09;缺页中断率 对于进程P…

【Linux】pidstat命令

作用&#xff1a;Report statistics for Linux tasks. 人话&#xff1a;进程级别的统计报告&#xff0c;用于分析进程的各种维度的指标&#xff08;CPU、内存、I/O、中断、上下文切换等等&#xff09; 这是一个综合型的命令&#xff0c;非常有用。 参数总结&#xff1a; -p: …

python处理Jenkins Job配置文件config.xml

文章目录一、准备config.xml文件二、增加字符串参数代码confix.xml文件会增加如下内容&#xff1a;创建的jenkins项目test1三、增加extendedChoice复选框参数代码config.xml会增加如下内容创建的jenkins项目参考文章一、准备config.xml文件 <flow-definition plugin"w…

【标准】要点整理-软件服务商交付能力评估标准

导读&#xff1a;中 国 软 件 行 业 协 会 团 体 标 准&#xff0c;软件服务商交付能力评估标准&#xff08;Evaluation Criteria Of Delivery Capability On Software Service Provider&#xff09;通过该标准可以对标所在公司交付能力情况&#xff0c;寻找差距。其中标注红色…

钟摆小游戏的开发过程

框架 <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport" content"widthdevice-width, initi…

K8S 快速入门(五)网络通信原理:Pod网络

一、Pod网络 1. Pod结构 Pod的特点&#xff1a;容器 1、有自己的IP地址 2、有自己的hostname 3、有自己的端口 Pod实际上可以理解为就是k8s云平台中的虚拟机&#xff0c;而这个pod内部封装的是由docker引擎所创建的容器&#xff0c;也可以理解为pod就是一个虚拟化分组&#xf…