Android 编程下 Touch 事件的分发和消费机制及代码
- 格式:doc
- 大小:97.50 KB
- 文档页数:8
移动端jstouch事件随着智能⼿机和平板电脑的普及, 越来越多的⼈⽤移动设备浏览⽹页,我们平时在pc浏览器上⽤的⿏标事件,⽐如:click, mouseover等,已经⽆法满⾜移动设备触摸屏的特点,触摸时代的到来,离不开那些触摸事件。
触摸事件包含4个接⼝。
TouchEvent代表当触摸⾏为在平⾯上变化的时候发⽣的事件.Touch代表⽤户⼿指与触摸平⾯间的⼀个接触点.TouchList代表⼀系列的Touch; ⼀般在⽤户多个⼿指同时接触触控平⾯时使⽤这个接⼝.DocumentTouch包含了⼀些创建 Touch对象与TouchList对象的便捷⽅法.TouchEvent接⼝可以响应基本触摸事件(如单个⼿指点击),它包含了⼀些具体的事件,事件类型:touchstart : 触摸开始(⼿指放在触摸屏上)touchmove: 拖动(⼿指在触摸屏上移动)touchend : 触摸结束(⼿指从触摸屏上移开)touchenter :移动的⼿指进⼊⼀个dom元素。
touchleave :移动的⼿指离开⼀个dom元素。
还有⼀个touchcancel,是在拖动中断时候触发。
事件属性:altKey : 该属性返回⼀个布尔值,表⽰在指定的事件发⽣时,Alt 键是否处于按下状态, event.altKey=true|false|1|0type : 触摸时触发的事件类型,⽐如touchstart每个触摸事件都包括了三个触摸属性列表:1. touches:当前位于屏幕上的所有⼿指触摸点的⼀个列表。
2. targetTouches:当前元素对象上所有触摸点的列表。
3. changedTouches:涉及当前事件的触摸点的列表。
它们都是⼀个数组,每个元素代表⼀个触摸点。
每个触摸点对应的Touch都有三对重要的属性,clientX/clientY、pageX/pageY、screenX/screenY。
其中screenX/screenY代表事件发⽣的位置对于屏幕的偏移量,clientX/clienYt和pageX/pageY都代表事件发⽣位置对应对象的偏移量,不过区别是clientX/clientY不包括对象滚动⽽隐藏的偏移量,⽽pageX/pageY包括对象滚动⽽隐藏的偏移量。
HTML5触摸事件(touchstart、touchmove和touchend)
HTML5中新添加了很多事件,但是由于他们的兼容问题不是很理想,应⽤实战性不是太强,所以在这⾥基本省略,咱们只分享应⽤⼴泛兼容不错的事件,⽇后随着兼容情况提升以后再陆续添加分享。
今天为⼤家介绍的事件主要是触摸事件:touchstart、touchmove和touchend。
⼀开始触摸事件touchstart、touchmove和touchend是iOs版Safari浏览器为了向开发⼈员传达⼀些信息新添加的事件。
因为iOs设备既没有⿏标也没有键盘,所以在为移动Safari浏览器开发交互性⽹页的时候,PC端的⿏标和键盘事件是不够⽤的。
在iPhone 3Gs发布的时候,其⾃带的移动Safari浏览器就提供了⼀些与触摸(touch)操作相关的新事件。
随后,Android上的浏览器也实现了相同的事件。
触摸事件(touch)会在⽤户⼿指放在屏幕上⾯的时候、在屏幕上滑动的时候或者是从屏幕上移开的时候出发。
下⾯具体说明:
touchstart事件:当⼿指触摸屏幕时候触发,即使已经有⼀个⼿指放在屏幕上也会触发。
touchmove事件:当⼿指在屏幕上滑动的时候连续地触发。
在这个事件发⽣期间,调⽤preventDefault()事件可以阻⽌滚动。
touchend事件:当⼿指从屏幕上离开的时候触发。
touchcancel事件:当系统停⽌跟踪触摸的时候触发。
关于这个事件的确切出发时间,⽂档中并没有具体说明,咱们只能去猜测了。
android事件响应和处理机制-回复Android事件响应和处理机制是指Android操作系统如何识别并处理由用户产生的各种输入事件,如触摸屏幕、按键、滚动等。
这个机制是Android应用程序和用户之间交互的重要部分,它确保了应用程序对用户输入做出及时和准确的响应。
本文将逐步介绍Android事件响应和处理机制的工作原理及相关的核心概念和类。
一、事件的传递顺序在Android中,事件的传递顺序遵循从上到下、从外到内的规则。
也就是说,系统会先将事件传递给Activity,然后由Activity传递给视图层次结构中的最底层View,并依次向上传递直到找到真正的事件处理者。
如果某个View处理了事件,后续的View将不再收到该事件。
事件的传递过程可以分为三个阶段:1. 捕获阶段:事件从最顶层的父容器向下传递,直到找到事件处理者为止。
在这个阶段,只有ViewGroup可以处理事件,View无法处理。
2. 目标阶段:事件传递到目标View后,由该View处理事件。
这里的处理包括两个部分:事件拦截和事件消费。
拦截意味着阻止事件继续向下传递,而消费则表示执行相应的操作。
3. 冒泡阶段:如果目标View没有完全消费事件,事件将继续向上传递给父容器的父容器,并以此类推,直到最顶层的父容器。
在冒泡阶段,只有ViewGroup可以处理事件,View无法处理。
二、事件分发机制Android通过三个核心类来实现事件的分发和处理:1. MotionEvent:用于封装触摸屏幕、鼠标或轨迹球事件的信息,包括触摸位置、触摸压力、触摸时间等。
2. KeyEvent:用于封装按键事件的信息,包括按键代码、按键动作、按键时间等。
3. View:是事件分发的关键,它封装了触摸事件和按键事件的处理方法,如onTouchEvent()和onKeyDown()。
View接收到事件后,会将事件分发给对应的处理方法。
在返回值中,它可以返回true表示事件已被消费,返回false表示事件未被消费。
android setcanceledontouchoutside原理摘要:1.Android setCanceledOnTouchOutside 原理概述2.setCanceledOnTouchOutside 的作用3.setCanceledOnTouchOutside 的工作原理4.使用setCanceledOnTouchOutside 的场景和注意事项5.总结正文:【1.Android setCanceledOnTouchOutside 原理概述】Android 中的setCanceledOnTouchOutside 是一个常用的属性,它主要用于处理触摸屏操作。
当一个触摸事件被触发时,setCanceledOnTouchOutside 可以取消当前触摸事件,防止其被其他控件接收。
这对于处理复杂的触摸交互逻辑非常有用。
【2.setCanceledOnTouchOutside 的作用】setCanceledOnTouchOutside 的作用主要体现在以下几个方面:- 避免触屏操作冲突:当用户在屏幕上同时触摸两个控件时,setCanceledOnTouchOutside 可以保证只有一个控件能够接收到触摸事件,避免出现多个控件同时响应触摸事件的情况。
- 优化用户体验:在一些场景下,用户可能会不小心触发其他控件的触摸事件,导致界面跳转或执行其他操作。
通过使用setCanceledOnTouchOutside,可以减少这种情况的发生,提高用户体验。
- 实现复杂交互逻辑:在一些复杂的触摸交互场景下,setCanceledOnTouchOutside 可以帮助开发者实现更加复杂的交互逻辑,例如游戏中的多点触控操作等。
【3.setCanceledOnTouchOutside 的工作原理】setCanceledOnTouchOutside 的工作原理主要基于Android 的触摸事件分发机制。
在Android 中,触摸事件会按照一定的优先级分发给各个控件。
android 事件传递原理Android是当前最流行的移动操作系统,它的事件传递机制是安卓开发中必须了解的一个问题。
本文将带您从简单到复杂的三个方面,逐步解析安卓事件传递的原理。
一、事件类型首先,我们需要知道Android事件的三大类型:1. 触摸事件:通过手指在屏幕上进行滑动、点击等手势操作触发。
2. 按键事件:用户在设备上的按键输入,如键盘、物理键等。
3. 轨迹球事件:主要针对轨迹球设备,但是由于这种设备很少被使用,所以这里不再深入讲解。
二、事件传递流程在了解了事件类型后,我们可以探讨一下事件传递的具体流程。
每一个事件都是通过ViewGroup或者View的dispatchTouchEvent()方法进行传递的。
我们可以将事件的传递过程抽象为TouchTarget链表。
当一个事件发生后,它会从Activity开始一层层向下传递,当找到能够处理该事件的View或ViewGroup时,则会调用其onTouchEvent()方法完成相应操作。
如果从顶层的ViewGroup开始寻找,当它的dispatchTouchEvent()方法返回true时,则整个事件处理结束。
如果返回false,则事件继续向下传递给下一个ViewGroup或View,直到找到可以处理这个事件的View为止。
由此可见,对于同一个事件,ViewGroup和父子View的处理有时是相互影响的,需要通过继承ViewGroup或者View,重写dispatchTouchEvent()和onTouchEvent()方法来控制事件传递的方式。
三、事件分发机制实际上,在ViewGroup中,事件传递机制涉及到的方法有三个:1. dispatchTouchEvent():负责分发事件。
2. onInterceptTouchEvent():拦截事件,阻止向下分发。
3. onTouchEvent():接收分发下来的事件。
其中,事件分发有三个阶段:1. 捕获阶段:事件从Activity传递到最外层的ViewGroup。
Android 事件处理机制Android 作为一款主流的移动操作系统,拥有强大的事件处理机制,使得开发者可以方便地对用户的操作进行响应和处理。
本文将介绍Android的事件处理机制及其相关的内容。
一、概述Android事件处理机制主要用于检测和响应用户在界面上的各种操作,包括点击、滑动、长按等。
通过灵活运用Android事件处理机制,开发者可以实现丰富多样的用户交互效果,提升应用的用户体验。
二、事件传递1. 事件传递的核心概念- 事件传递分为三个阶段:事件分发、事件拦截、事件处理。
- 事件的传递是从上至下的过程,即从Activity到ViewGroup,再到最终的View。
2. 事件分发- 事件首先会被分发给当前界面的顶层View的dispatchTouchEvent()方法进行处理。
- 顶层View会根据具体的触摸事件类型(DOWN、MOVE、UP、CANCEL)进行相应的处理。
3. 事件拦截- 如果顶层View在处理事件后,认为自己不能完全处理该事件,则会将事件交给子View处理,通过调用子View的dispatchTouchEvent()方法传递事件给子View。
- 子View可以通过重写onInterceptTouchEvent()方法来决定是否拦截事件。
4. 事件处理- 最终,事件会传递到具体的View上,并通过重写onTouchEvent()方法来实现事件的处理。
- View可以根据具体的事件类型(点击、滑动、长按等)执行相应的操作。
三、事件分发机制1. 事件分发的层级关系- Android中的事件分发机制是基于层级关系的,即不同的ViewGroup和View之间存在不同的事件分发机制。
- ViewGroup和View都重写了dispatchTouchEvent()方法,用于对事件进行分发。
2. ViewGroup中的事件分发- ViewGroup会根据具体的事件类型,将事件传递给自己的子View。
Androidtouchmode和focusableInTouchMode分析 ⾸先我们来看看touch mode的定义。
它是⽤户和⼿机进⾏交互时view层次结构的⼀个状态。
它本⾝是很容易理解的,代表了最近⼀次的交互是否是通过触摸屏发⽣的,因为在Android设备上还存在别的交互⽅式,⽐如D-pad、滚动球等等。
为什么Android会引⼊这样⼀个mode呢?这是因为从交互、设计⽅⾯考虑,当⽤户直接使⽤keys或trackball与UI进⾏交互的时候,必须先使⽬标控件获得焦点(⽐如⾼亮起来),这样⽤户才会注意到是什么控件在接收输⼊。
然⽽如果设备⽀持触摸⼿势的话,⽤户直接⽤⼿指点击控件,这个时候当然就没必要将⽬标控件⾼亮了(即获取焦点)。
对于⼀个拥有触摸屏功能的设备⽽⾔, ⼀旦⽤户⽤⼿点击屏幕, 设备会⽴刻进⼊touch mode。
这时候被点击的控件只有isFocusableInTouchMode()为true的时候才会获得focus,⽐如EditText控件。
其他可以触摸的控件⽐如Button(其isFocusableInTouchMode默认为false), 当被点击的时候不会获取焦点,它们只是简单地执⾏onClick事件⽽已。
任何时候只要⽤户点击key或滚动trackball, 设备就会退出touch mode,并且找⼀个view将焦点置于其上,这样⽤户可以在不需要再次触摸屏幕的情况下接着和UI进⾏交互。
touch mode在整个系统运⾏期间都是有效的(跨activities),任何时候都可以调⽤View.isInTouchMode()⽅法来查看当前设备是否处于touch mode状态。
从上⾯的介绍我们能看出来,在触摸屏下的view,设置了focusableInTouchMode和没设置在⽤户体验上是不同的,其实内部的处理逻辑也是不同的,⽐如:没设置这个属性的控件在⽤户触摸交互时是不会获得focus的,也就是说focus在touch过程中是不会改变的,只是其onClickListener如果设置了的话会在up事件到来时触发。
touch事件的实现在开始描述touch事件之前,需要先描述⼀下多触式系统中特有的touch对象(android和iOS乃⾄nokia最新的meego系统都模拟了类似的对象)。
这个对象封装⼀次屏幕触摸,⼀般来⾃于⼿指。
它在touch事件触发的时候产⽣,可以通过touch event handler的event对象取到移动端触屏滑动的效果其实就是图⽚轮播,在PC的页⾯上很好实现,绑定click和mouseover等事件来完成。
但是在移动设备上,要实现这种轮播的效果,就需要⽤到核⼼的touch事件。
处理touch事件能跟踪到屏幕滑动的每根⼿指。
以下是四种touch事件touchstart: //⼿指放到屏幕上时触发touchmove: //⼿指在屏幕上滑动式触发touchend: //⼿指离开屏幕时触发touchcancel: //系统取消touch事件的时候触发,这个好像⽐较少⽤ 每个触摸事件被触发后,会⽣成⼀个event对象,event对象⾥额外包括以下三个触摸列表:touches: //当前屏幕上所有⼿指的列表targetTouches: //当前dom元素上⼿指的列表,尽量使⽤这个代替toucheschangedTouches: //涉及当前事件的⼿指的列表,尽量使⽤这个代替touches 这些列表⾥的每次触摸由touch对象组成,touch对象⾥包含着触摸信息,主要属性如下:clientX / clientY: //触摸点相对浏览器窗⼝的位置pageX / pageY: //触摸点相对于页⾯的位置screenX / screenY: //触摸点相对于屏幕的位置identifier: //touch对象的IDtarget: //当前的DOM元素注意事项:⼿指在滑动整个屏幕时,会影响浏览器的⾏为,⽐如滚动和缩放。
所以在调⽤touch事件时,要注意禁⽌缩放和滚动。
1.禁⽌缩放通过meta元标签来设置。
touchmovecallback参数意思在 JavaScript 中,touchmove 是一个 Touch 事件,在移动计算机屏幕上的手指时触发。
当用户在触摸屏上滑动手指时,会触发 touchmove 事件。
这个事件可以用于许多交互应用程序中,例如绘图应用、滚动页面、游戏等。
touchmove 事件具有一个参数,即 touchmovecallback。
touchmovecallback 是一个回调函数,它会在 touchmove 事件被触发时执行。
回调函数的参数包含了与触摸相关的信息,可以根据这些信息来处理相应的操作。
回调函数的参数包括以下属性:1. touches:一个 TouchList 对象,它表示当前屏幕上所有触摸点的列表。
每个触摸点是一个 Touch 对象,其中包含了触摸点的坐标、大小、压力等信息。
2. targetTouches:一个 TouchList 对象,它表示当前元素上所有触摸点的列表。
这些触摸点必须是属于当前元素的触摸点。
3. changedTouches:一个 TouchList 对象,它表示了最近一次触摸事件中的变化触摸点的列表。
通常情况下,changedTouches 只包含了一个触摸点,即当前触摸点。
通过这些触摸点的信息,可以获取触摸点的坐标和偏移量,进而实现一些交互操作。
例如可以通过计算触摸点之间的差值,来判断用户的滑动方向和速度,进而实现手势识别、滚动操作等。
以下是一个简单的示例代码,演示了如何使用 touchmovecallback 参数来捕获触摸点的坐标和偏移量:```javascript//获取元素const element = document.getElementById('myElement');//触摸移动事件处理程序function handleTouchMove(event)//获取触摸点信息const touch = event.changedTouches[0];//获取触摸点的坐标const x = touch.clientX;const y = touch.clientY;//处理触摸点坐标//...//获取触摸点的偏移量const dx = touch.clientX - touch.pageX;const dy = touch.clientY - touch.pageY;//处理触摸点偏移量//...//添加触摸移动事件监听器element.addEventListener('touchmove', handleTouchMove);```上述代码通过监听元素的 touchmove 事件,当手指在元素上滑动时,会触发 handleTouchMove 函数,并传入事件对象。
Android 编程下Touch 事件的分发和消费机制(一)2013年06月04日09:59供稿中心:课工场摘要:Android 中与Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev)、Android 中与Touch 事件相关的方法包括:dispatchTouchEvent(MotionEvent ev)、onInterceptTouchEvent(MotionEvent ev)、onTouchEvent(MotionEvent ev);能够响应这些方法的控件包括:ViewGroup、View、Activity。
方法与控件的对应关系如下表所示:从这张表中我们可以看到ViewGroup 和View 对与Touch 事件相关的三个方法均能响应,而Activity 对onInterceptTouchEvent(MotionEvent ev) 也就是事件拦截不进行响应。
另外需要注意的是View 对dispatchTouchEvent(MotionEvent ev) 和onInterceptTouchEvent(MotionEvent ev) 的响应的前提是可以向该View 中添加子View,如果当前的View 已经是一个最小的单元View(比如TextView),那么就无法向这个最小View 中添加子View,也就无法向子View 进行事件的分发和拦截,所以它没有dispatchTouchEvent(MotionEvent ev) 和onInterceptTouchEvent(MotionEvent ev),只有onTouchEvent(MotionEvent ev)。
一、Touch 事件分析▐事件分发:public boolean dispatchTouchEvent(MotionEvent ev)Touch 事件发生时Activity 的dispatchTouchEvent(MotionEvent ev) 方法会以隧道方式(从根元素依次往下传递直到最内层子元素或在中间某一元素中由于某一条件停止传递)将事件传递给最外层View 的dispatchTouchEvent(MotionEvent ev) 方法,并由该View 的dispatchTouchEvent(MotionEvent ev) 方法对事件进行分发。
dispatchTouchEvent 的事件分发逻辑如下:如果return true,事件会分发给当前View 并由dispatchTouchEvent 方法进行消费,同时事件会停止向下传递;如果return false,事件分发分为两种情况:如果当前View 获取的事件直接来自Activity,则会将事件返回给Activity 的onTouchEvent 进行消费;如果当前View 获取的事件来自外层父控件,则会将事件返回给父View的 onTouchEvent 进行消费。
如果返回系统默认的super.dispatchTouchEvent(ev),事件会自动的分发给当前View 的onInterceptTouchEvent 方法。
▐事件拦截:public boolean onInterceptTouchEvent(MotionEvent ev)在外层View 的dispatchTouchEvent(MotionEvent ev) 方法返回系统默认的super.dispatchTouchEvent(ev) 情况下,事件会自动的分发给当前View 的onInterceptTouchEvent 方法。
onInterceptTouchEvent 的事件拦截逻辑如下:如果onInterceptTouchEvent 返回true,则表示将事件进行拦截,并将拦截到的事件交由当前View 的onTouchEvent 进行处理;如果onInterceptTouchEvent 返回false,则表示将事件放行,当前View 上的事件会被传递到子View 上,再由子View 的dispatchTouchEvent 来开始这个事件的分发;如果onInterceptTouchEvent 返回super.onInterceptTouchEvent(ev),事件默认会被拦截,并将拦截到的事件交由当前View 的onTouchEvent 进行处理。
▐事件响应:public boolean onTouchEvent(MotionEvent ev)在dispatchTouchEvent 返回super.dispatchTouchEvent(ev) 并且onInterceptTouchEvent 返回true 或返回super.onInterceptTouchEvent(ev) 的情况下onTouchEvent 会被调用。
onTouchEvent 的事件响应逻辑如下:如果事件传递到当前View 的onTouchEvent 方法,而该方法返回了false,那么这个事件会从当前View 向上传递,并且都是由上层View 的onTouchEvent 来接收,如果传递到上面的onTouchEvent 也返回false,这个事件就会“消失”,而且接收不到下一次事件。
如果返回了true 则会接收并消费该事件。
如果返回super.onTouchEvent(ev) 默认处理事件的逻辑和返回false 时相同。
到这里,与Touch 事件相关的三个方法就分析完毕了。
下面的内容会通过各种不同的的测试案例来验证上文中三个方法对事件的处理逻辑。
二、Touch 案例介绍同样在开始进行案例分析之前,我需要说明测试案例的结构,因为所有的测试都是针对这一个案例来进行的,测试中只是通过修改每个控件中与Touch 事件相关的三个方法的返回值来体现不同的情况。
先来看张图:上面的图为测试案例的布局文件UI 显示效果,布局文件代码如下:1 2 3 4 5 6 7 8 91011121314151617<?xml version="1.0" encoding="utf-8"?><cn.sunzn.tevent.TouchEventFatherxmlns:android="/apk/res/android" android:layout_width="fill_parent"android:layout_height="fill_parent"android:background="#468AD7"android:gravity="center"android:orientation="vertical" ><cn.sunzn.tevent.TouchEventChildsandroid:id="@+id/childs"android:layout_width="200dp"android:layout_height="200dp"android:layout_gravity="center"android:background="#E1110D"android:text="@string/hello" /></cn.sunzn.tevent.TouchEventFather>蓝色背景为一个自定义控件TouchEventFather,该控件为外层View,继承自LinearLayout,实现代码如下:1 2 3 4 package cn.sunzn.tevent;import android.content.Context; import android.util.AttributeSet;5 6 7 8 910111213141516171819202122232425262728293031323334import android.util.Log;import android.view.MotionEvent;import android.widget.LinearLayout;public class TouchEventFather extends LinearLayout {public TouchEventFather(Context context) {super(context);}public TouchEventFather(Context context, AttributeSet attrs) {super(context, attrs);}public boolean dispatchTouchEvent(MotionEvent ev) {Log.e("sunzn", "TouchEventFather | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.dispatchTouchEvent(ev);}public boolean onInterceptTouchEvent(MotionEvent ev) {Log.i("sunzn", "TouchEventFather | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.onInterceptTouchEvent(ev);}public boolean onTouchEvent(MotionEvent ev) {Log.d("sunzn", "TouchEventFather | onTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.onTouchEvent(ev);}}红色背景为一个自定义控件TouchEventChilds,该控件为内层View,为TouchEventFather 的子View,同样继承自LinearLayout,实现代码如下:1 2 3 4 5 6 package cn.sunzn.tevent;import android.content.Context; import android.util.AttributeSet; import android.util.Log;import android.view.MotionEvent;7 8 910111213141516171819202122232425262728293031323334import android.widget.LinearLayout;public class TouchEventChilds extends LinearLayout {public TouchEventChilds(Context context) {super(context);}public TouchEventChilds(Context context, AttributeSet attrs) {super(context, attrs);}public boolean dispatchTouchEvent(MotionEvent ev) {Log.e("sunzn", "TouchEventChilds | dispatchTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.dispatchTouchEvent(ev);}public boolean onInterceptTouchEvent(MotionEvent ev) {Log.i("sunzn", "TouchEventChilds | onInterceptTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.onInterceptTouchEvent(ev);}public boolean onTouchEvent(MotionEvent ev) {Log.d("sunzn", "TouchEventChilds | onTouchEvent --> " + TouchEventUtil.getTouchAction(ev.getAction()));return super.onTouchEvent(ev);}}接着实现Activity 的代码,因为控件所有的事件都是通过Activity 的dispatchTouchEvent 进行分发的;除此之外还需要重写Activity 的onTouchEvent 方法,这是因为如果一个控件直接从Activity 获取到事件,这个事件会首先被传递到控件的dispatchTouchEvent 方法,如果这个方法return false,事件会以冒泡方式返回给Activity 的onTouchEvent 进行消费。