以前开发画板组件时,要添加一个长按监听事件,这个画板实际上就是继承自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. MVC學習網站

    http://www.cnblogs.com/haogj/archive/2011/11/23/2246032.html

  2. Qt Creater中的.pro文件和.pri文件

    初学Qt,使用Qt Creater打开Demo "QT 3D Basic Shapes C++ Example",发现除了pro文件外,还有一个pri文件,在此小白一下! *.pr ...

  3. 阿里云提出的漏洞(Phpcms V9某处逻辑问题导致getshell漏洞解决方法)的问题

    最近从阿里云云盾检测流出来的,相比使用阿里云服务器的朋友已经收到漏洞提醒:Phpcms V9某处逻辑问题导致getshell漏洞解决方法,这个漏洞怎么办呢?CMSYOU在这里找到针对性解决办法分享给大 ...

  4. SQL 语句判断记录是否存在(最简洁简单性能最优)

    今天查了下,发现网上的没有一个sql语句写的好的. 判断记录是否存在,要不是语句不够简洁,要不就是性能有很大问题. 我进行了优化后,最简洁简单性能最优的的sql语句,用来判断表中的记录是否存在: se ...

  5. js合并.css合并工具

    http://www.neoease.com/css-javascript-combo-tool/ http://www.neoease.com/minimize-javascript-files-u ...

  6. Linux 查看磁盘分区、文件系统、磁盘的使用情况相关的命令和工具介绍

    https://www.cnblogs.com/alexyuyu/articles/3454907.html

  7. rpc框架 SimpleXMLRP

    一台电脑去控制另一台电脑干事情,最常见的就是web. 用户get/post一个url,服务端根据url地址和参数去做相应的事情把结果返回给客户端. server.py #coding=utf8 fro ...

  8. python连接mysql数据库封装

    源码: import pymysql class MysqlConnect(object): # 魔术方法, 初始化, 构造函数 def __init__(self, host, user, pass ...

  9. vue中使用动态echart图表

    <template> <div class="block"> <div class="title">展会实时人流里统计< ...

  10. c 各种编译器(gcc clang)

    很多时候,出现一些类似GNU,GCC,CLANG,LLVM等与编译器有关的名词的时候,都不太清楚它到底是干嘛的,理解这些东西后, 对于xcode中很多配置型的需求修改起来都会得心应手,因此有必要了解透 ...