以前开发画板组件时,要添加一个长按监听事件,这个画板实际上就是继承自View的一个自定义组件。

首先,设置好长按事件发生时要触发的操作:

  private class LongPressRunnable implements Runnable {

        private int x, y;

        public void setPressLocation(float x, float y) {
this.x = (int) x;
this.y = (int) y;
} @Override
public void run() {
Log.i("发生长按事件,位置在:" + x + "、" + y);
} }

接下来,编写自定义的View,重点在覆写dispatchTouchEvent(MotionEvent)方法:

public class MyView extends View {

        ...

    /**
* 当长按事件发生时,要触发的任务
*/
private LongPressRunnable longPressRunnable = new LongPressRunnable(); @Override
public boolean dispatchTouchEvent(MotionEvent event) { if (longPressRunnable != null) { //TODO 这里可以增加一些规则,比如:模糊XY的判定,使长按更容易触发 removeCallbacks(longPressRunnable); if (event.getAction() == MotionEvent.ACTION_DOWN
&& event.getPointerCount() == 1) {
postCheckForLongTouch(event.getX(), event.getY());
}
} return true;
} private void postCheckForLongTouch(float x, float y) { longPressRunnable.setPressLocation(x, y);
      
postDelayed(longPressRunnable, 500);
}
}

原理很简单,长按事件的本质是:手指触摸某个点保持不移动,也就是touch的时候仅仅发生ACTION_DOWN事件,不发生ACTION_MOVE和ACTION_UP事件,这样经过一定时间(这里是500毫秒)则成功触发长按事件。

所以一个长按事件的周期是On Touch Down ---> 500ms ---> On Long Press。

接下来分析上面的实现:当我们收到Touch事件时,不管是什么事件,先删除上一次设置好的longPressRunnable,

removeCallbacks(longPressRunnable);

这意味着上一次触摸周期没有触发长按操作。

然后判断事件类型,如果是“单指ACTION_DOWN”事件则表明有可能会触发长按操作,那么我们通过View.postDelayed()方法将longPressRunnable放进这个View所在线程的任务队列中,并延迟500毫秒执行,

if (event.getAction() == MotionEvent.ACTION_DOWN && event.getPointerCount() == 1) {
postCheckForLongTouch(event.getX(), event.getY());
}
private void postCheckForLongTouch(float x, float y) {
longPressRunnable.setPressLocation(x, y);
postDelayed(longPressRunnable, 500);
}

如果在这500毫秒内,用户的手指没有移动或抬起,也就是不会有任何touch事件到来,则该longPressRunnable会在500毫秒后运行,一个长按操作就完成了。

如果在这500毫秒内用户的手指移动或抬起了,那么新的touch事件到来,longPressRunnable也会被移除。

以上就是整个实现,这个实现有个需要优化的地方,就是//TODO那里,由于人的手指并没有那么精细,在长按过程中可能会有一点移动,这往往会导致长按失败,所以我们可以在//TODO那里添加对ACTION_MOVE事件的处理,忽略一些细微的移动事件,留给读者自行实现吧:D

为自定义的View添加长按事件的更多相关文章

  1. 给View 添加手势,点击无反应 如何给View添加点击事件,手势方法

    项目中有很多地方需要添加点击事件,重复代码很多,所以做了一个UIView的分类,专门做点击事件使用.项目地址:UIView-Tap 代码很简单,主要有一点就是注意分类不能直接添加属性,需要用到运行时相 ...

  2. 为 UIButton 添加长按事件

    UIButton *aBtn=[UIButtonbuttonWithType:UIButtonTypeCustom]; [aBtn setFrame:CGRectMake(40, 100, 60, 6 ...

  3. datatables添加长按事件

    长按事件 $.fn.longPress = function (fn) { var timeout = undefined; var $this = this; for (var i = 0; i & ...

  4. View,ViewGroup的Touch事件的分发机制

    原帖地址:http://blog.csdn.net/xiaanming/article/details/21696315 ViewGroup的事件分发机制 我们用手指去触摸Android手机屏幕,就会 ...

  5. TextView AutoLink, ClikSpan 与长按事件冲突的解决

    前言 首先,我们先来复习一下 autoLink 和 ClickableSpan 是干什么用的. autoLink 当中有五个属性值:分别是 phone.email.map.web.all 和 none ...

  6. Andriod 从源码的角度详解View,ViewGroup的Touch事件的分发机制

    转自:xiaanming的博客(http://blog.csdn.net/xiaanming/article/details/21696315) 今天这篇文章主要分析的是Android的事件分发机制, ...

  7. 【Android - 自定义View】之不同事件的处理

    在Android的自定义View中,往往需要处理一系列的事件,如触摸事件.双击事件.缩放事件等.本文将这些事件及其处理进行总结.本文将持续更新,将我在自定义View的实践中用到的事件及其处理进行总结. ...

  8. Android系统中自定义按键的短按、双击、长按事件

    在项目中碰到这样的问题: 由于系统中的按键在底层做了重新定义或者新增了按键,此时需要在APP层对按键事件(keyevent)做分解处理,模拟Android系统做法,把keyevent分解成: 1.单击 ...

  9. Android自定义长按事件

    Android系统自带了长按事件,setOnLongClickListener即可监听.但是有时候,你不希望用系统的长按事件,比如当希望长按的时间更长一点的时候.这时候就需要自己来定义这个长按事件了. ...

随机推荐

  1. 续:纠正:ubuntu【7.04】可以安装,而且完美的安装 ! for《Oracle-10.2.0.1,打补丁10.2.0.5:在 debian 版本4【不含4】以上,及 ubuntu 7.04【不含7.04】以上都可以安装!》

    n次的测试后,最终证明,如下做法,可以完美安装. 中间都不带任何一个错误的!!!完美! dhclient vi /etc/profile ll cd /etc/apt/ mv sources.list ...

  2. SQLServer查看存储过程的方法

    使用 sp_helptext 查看存储过程的定义 在对象资源管理器中,连接到 数据库引擎实例,再展开该实例. 在工具栏上,单击“新建查询”. 在查询窗口中,输入下列语句.更改数据库名称和存储过程名称以 ...

  3. JQ 使用toggle实现DIV的隐藏和显示

    $('.submenuA').toggle( function () { $(this).next('div').show(); }, function () { $(this).next('div' ...

  4. anaconda-ks.cfg详解

    https://blog.csdn.net/whyhonest/article/details/7555229

  5. Javascript富文本编辑器

    分享几款Javascript富文本编辑器 ueditor jqframework xheditor htmlbox kindeditor wymeditor jhtmlarea markitup ck ...

  6. SpringMVC -- 梗概--源码--贰--RestFul收参(了解) @PathVariable

    1>定制方式: //如下两个路径都可以访问到如下方法,请求路径不同,则name61和pwd61匹配到的值不同 //http://localhost:8989/appname/ful/lime/1 ...

  7. mysql字段集合中如何去除其中一个元素

    在一对多方案中,我们用逗号拼接进行存储,避免存储多条,或者分表,那么此时出现了存储上如果需要修改的话 就带来了难度,比如规则记录表如下 如果2号规则被删除,那么这张表的所有有2的记录也要被清除掉,此时 ...

  8. SpringBoot application.properties (application.yml)优先级从高到低

    SpringBoot application.properties(application.yml) 优先级从高到低 SpringBoot配置文件优先级从高到低 =================== ...

  9. hive-数据模型

    hive支持四种数据模型 • external table• table• partition• bucket 为了避免table名称冲突,hive用database作为顶层域名,如果不设定datab ...

  10. SVN设置没有写log不能commit

    操作方法:在SVN的Repositories下,找到要配置的项目,在项目目录下找到hooks文件夹,在其下创建pre-commit.bat文件,把下面复制进去就可以了(无需重启,如果改动,保存bat文 ...