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

最新文章

  1. 孙鑫C++教程留下来的作业--如何让工具栏在原来隐藏的位置出现
  2. mysql数据库安装及使用
  3. PHP中实现MySQL嵌套事务的两种解决方案
  4. 关于IOS的证书、App ID、设备、Provisioning Profile详述
  5. struts2介绍
  6. linux系统执行多条命令,linux系统执行复合命令
  7. JavaScript 找出数组中重复的元素
  8. Oracle- 用户管理
  9. RSA 非对称加密 数字签名 数字证书
  10. Period(kmp)
  11. select2简单例子
  12. Java常用代码段 - 未完待续
  13. 数据结构中的棧在C#中的实现
  14. listview的简单封装
  15. C语言基础 - 实现动态数组并增加内存管理
  16. Piggy Back_KEY
  17. 基于Java的WebSocket推送
  18. canvas焰火特效
  19. 请解释ASP.NET 中的web 页面与其隐藏类之间的关系?
  20. Laravel自带SMTP邮件组件实现发送邮件(QQ、163、企业邮箱都可)

热门文章

  1. classpath路劲
  2. mysql中如何开启binlog?开启二进制日志文件?binary log?
  3. Git------如何使用Git Bash Here提交代码
  4. Python easyGUI 文件对比 覆盖保存
  5. 采用get方式提交数据到服务器实例
  6. 基于github+hexo搭建个人博客(window)
  7. PHP代码审计笔记--任意文件下载漏洞
  8. 一句话木马:ASPX篇
  9. Sharepoint文档的CAML分页及相关筛选记录
  10. Python时间戳与时间字符串互相转换实例代码