以前开发画板组件时,要添加一个长按监听事件,这个画板实际上就是继承自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. 安装Python模块:pygame

    Pygame项目托管在代码分享网站Bitbucket中.要在Windows系统中安装Pygame,请访问https://bitbucket.org/pygame/pygame/downloads/ , ...

  2. 【转载】MongoDB集群和实战详解

    1.概述 最近有同学和网友私信我,问我MongoDB方面的问题:这里我整理一篇博客来赘述下MongoDB供大家学习参考,博客的目录内容如下: 基本操作 CRUD MapReduce 本篇文章是基于Mo ...

  3. 最简单安装laravel

    http://laravelacademy.org/resources-download

  4. npm 安装碰到SSL问题

    经过仔细排查和google,原来是ssl 的问题: 解决办法:  npm config set strict-ssl false  

  5. linux环境中安装NRPE插件执行远程"本地资源"检查?NRPE安装?

    需求描述: 在安装完nagios之后,需要对本地资源进行监控,比如磁盘空间的使用,进程数,swap空间,等等.这些都不是通过网络提供出来的, 所以,都是本地资源,可以通过NRPE插件实现在客户端中采集 ...

  6. MTK 隐藏上方的状态栏

    步骤一: 源码/frameworks/base/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.ja ...

  7. windows 7 64位出现Oracle中文乱码

    提示oracle客户端无法连接指定字符 安装好客户端之后,如图 将数据库dbhome_1中的network文件夹全部复制到客户端,如图 然后在设置环境变量:F:\app\Administrator\p ...

  8. Web实时通信之Socket.IO

    前面两篇文章使用了Ajax long polling和WebSocket两种常用的Web实时通信方式构建了简单的聊天程序. 但是,由于浏览器的兼容问题,不是所有的环境都可以使用WebSocket这种比 ...

  9. 深度缓存ZBuffer线性化

    double linearizeDepth(double nearz,double farz,double depth) { depth = 2.0 * depth - 1.0; return (2. ...

  10. pip导出安装包及批量安装

    python导出安装包及版本 pip freeze > requirements.txt 批量安装pip install -r requirements.txt