Android手掌抑制功能的实现

2024-01-15 16:30

本文主要是介绍Android手掌抑制功能的实现,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        最近需要实现一个功能,在Activity中有一个手写区域,为了更好的用户体验,需要满足即使整个手掌放在屏幕上时(android平板,屏幕比较大)也只响应手写区域内的操作,即在支持多点触控的情况下,只响应指定的区域,我将这个功能称作“手掌抑制”,即在手写时,手掌放在屏幕上面不做任何响应。

        初看这个功能很简单,按照之前处理listview、gridview里面的子view不能响应的方式,只要在activity层不拦截向手写view传递的消息即可实现想要的效果,但经过实际测试和对android消息机制的详细研究发现,要实现这个功能会有点小复杂。

 

一、android的消息传递机制:

1、基础知识:

        (1) 所有Touch事件都被封装成了MotionEvent对象,包括Touch的位置、时间、历史记录以及第几个手指(多指触摸)等。

        (2) 事件类型分为ACTION_DOWN, ACTION_UP, ACTION_MOVE, ACTION_POINTER_DOWN, ACTION_POINTER_UP, ACTION_CANCEL,每个事件都是以ACTION_DOWN开始ACTION_UP结束。

        (3) 对事件的处理包括三类:

        传递——dispatchTouchEvent()

        拦截——onInterceptTouchEvent()

        消费——onTouchEvent()和OnTouchListener

 

2、传递流程

        (1) 事件从Activity.dispatchTouchEvent()开始传递,只要没有被停止或拦截,从最上层的View(ViewGroup)开始一直往下(子View)传递。子View可以通过onTouchEvent()对事件进行处理。

        (2) 事件由父View(ViewGroup)传递给子View,ViewGroup可以通过onInterceptTouchEvent()对事件做拦截,停止其往下传递。

        (3) 如果事件从上往下传递过程中一直没有被停止,且最底层子View没有消费事件,事件会反向往上传递,这时父View(ViewGroup)可以进行消费,如果还是没有被消费的话,最后会到Activity的onTouchEvent()函数。

        (4) 如果View没有对ACTION_DOWN进行消费,之后的其他事件不会传递过来。

        (5) OnTouchListener优先于onTouchEvent()对事件进行消费。

        上面的消费即表示相应函数返回值为true。

 

3、实际情况:

        能够响应事件处理方法的控件包括:ViewGroup、View、Activity,各类控件对三个事件响应处理方法的支持情况如下:

 

         这三个控件,Activity是处于最外层的,消息的传递首先是系统回调消息给Activity,Activity将消息传递给每一个ViewGroup,然后ViewGroup会将消息传递给相应地子View。

        本文所描述的手写控件是一个view,在有系统消息回调时只有上层控件将消息分发下来,它才能够消费和处理这些消息。

 

二、问题现象:

        接着我们进入正题,按照我在开篇介绍的那种处理方式,写一个手写view,在Activity和ViewGroup(自定义一个Layout即可)层将消息分发给该view,目前的代码看上去是这样子的:

 

public class DrawView extends View {public DrawView(Context context, AttributeSet attrs, int defStyle) {super(context, attrs, defStyle);initPaintView( );}public DrawView(Context context, AttributeSet attrs) {super(context, attrs);initPaintView( );}public DrawView(Context context) {super(context);initPaintView( );}public void clear() {  if (null != mPath) {  mPath.reset();  invalidate();  }  }  private void initPaintView() {  mPaint.setAntiAlias(true);  mPaint.setColor(Color.WHITE);  mPaint.setStyle(Paint.Style.STROKE);  mPaint.setStrokeJoin(Paint.Join.ROUND);  mPaint.setStrokeWidth(5f);  }@Overrideprotected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {super.onMeasure(widthMeasureSpec, heightMeasureSpec);mViewWidth = MeasureSpec.getSize(widthMeasureSpec);   //获取ViewGroup宽度    mViewHeight = MeasureSpec.getSize(heightMeasureSpec);  //获取ViewGroup高度}@Override  protected void onDraw(Canvas canvas) {  canvas.drawPath(mPath, mPaint);  }  public boolean inArea( float x, float y ){return ( x >= 0 && x <= mViewWidth && y >= 0 && y <= mViewHeight)?true:false;}@Override  public boolean onTouchEvent(MotionEvent event) {float eventX = event.getX( );  float eventY = event.getY( );switch (event.getAction()) {case MotionEvent.ACTION_DOWN: {  mPath.moveTo(eventX, eventY);mLastTouchX = eventX;  mLastTouchY = eventY;invalidate( );}  return true;  case MotionEvent.ACTION_MOVE:{drawView( event, eventX, eventY );}break;case MotionEvent.ACTION_UP:{  drawView( event, eventX, eventY );}  break;  default:  return false;  }  return true;  }private void drawView( MotionEvent event, float eventX, float eventY ){resetDirtyRect(eventX, eventY);  int historySize = event.getHistorySize();  for (int i = 0; i < historySize; i++) {  float historicalX = event.getHistoricalX(i);  float historicalY = event.getHistoricalY(i);  getDirtyRect(historicalX, historicalY);  mPath.lineTo(historicalX, historicalY);  }  mPath.lineTo(eventX, eventY);  invalidate((int) (mDirtyRect.left - HALF_STROKE_WIDTH), 

这篇关于Android手掌抑制功能的实现的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/609513

相关文章

Android 12解决push framework.jar无法开机的方法小结

《Android12解决pushframework.jar无法开机的方法小结》:本文主要介绍在Android12中解决pushframework.jar无法开机的方法,包括编译指令、框架层和s... 目录1. android 编译指令1.1 framework层的编译指令1.2 替换framework.ja

Flutter实现文字镂空效果的详细步骤

《Flutter实现文字镂空效果的详细步骤》:本文主要介绍如何使用Flutter实现文字镂空效果,包括创建基础应用结构、实现自定义绘制器、构建UI界面以及实现颜色选择按钮等步骤,并详细解析了混合模... 目录引言实现原理开始实现步骤1:创建基础应用结构步骤2:创建主屏幕步骤3:实现自定义绘制器步骤4:构建U

使用Python创建一个功能完整的Windows风格计算器程序

《使用Python创建一个功能完整的Windows风格计算器程序》:本文主要介绍如何使用Python和Tkinter创建一个功能完整的Windows风格计算器程序,包括基本运算、高级科学计算(如三... 目录python实现Windows系统计算器程序(含高级功能)1. 使用Tkinter实现基础计算器2.

SpringBoot中四种AOP实战应用场景及代码实现

《SpringBoot中四种AOP实战应用场景及代码实现》面向切面编程(AOP)是Spring框架的核心功能之一,它通过预编译和运行期动态代理实现程序功能的统一维护,在SpringBoot应用中,AO... 目录引言场景一:日志记录与性能监控业务需求实现方案使用示例扩展:MDC实现请求跟踪场景二:权限控制与

Android开发环境配置避坑指南

《Android开发环境配置避坑指南》本文主要介绍了Android开发环境配置过程中遇到的问题及解决方案,包括VPN注意事项、工具版本统一、Gerrit邮箱配置、Git拉取和提交代码、MergevsR... 目录网络环境:VPN 注意事项工具版本统一:android Studio & JDKGerrit的邮

Android实现定时任务的几种方式汇总(附源码)

《Android实现定时任务的几种方式汇总(附源码)》在Android应用中,定时任务(ScheduledTask)的需求几乎无处不在:从定时刷新数据、定时备份、定时推送通知,到夜间静默下载、循环执行... 目录一、项目介绍1. 背景与意义二、相关基础知识与系统约束三、方案一:Handler.postDel

使用Python实现IP地址和端口状态检测与监控

《使用Python实现IP地址和端口状态检测与监控》在网络运维和服务器管理中,IP地址和端口的可用性监控是保障业务连续性的基础需求,本文将带你用Python从零打造一个高可用IP监控系统,感兴趣的小伙... 目录概述:为什么需要IP监控系统使用步骤说明1. 环境准备2. 系统部署3. 核心功能配置系统效果展

Python实现微信自动锁定工具

《Python实现微信自动锁定工具》在数字化办公时代,微信已成为职场沟通的重要工具,但临时离开时忘记锁屏可能导致敏感信息泄露,下面我们就来看看如何使用Python打造一个微信自动锁定工具吧... 目录引言:当微信隐私遇到自动化守护效果展示核心功能全景图技术亮点深度解析1. 无操作检测引擎2. 微信路径智能获

Python中pywin32 常用窗口操作的实现

《Python中pywin32常用窗口操作的实现》本文主要介绍了Python中pywin32常用窗口操作的实现,pywin32主要的作用是供Python开发者快速调用WindowsAPI的一个... 目录获取窗口句柄获取最前端窗口句柄获取指定坐标处的窗口根据窗口的完整标题匹配获取句柄根据窗口的类别匹配获取句

在 Spring Boot 中实现异常处理最佳实践

《在SpringBoot中实现异常处理最佳实践》本文介绍如何在SpringBoot中实现异常处理,涵盖核心概念、实现方法、与先前查询的集成、性能分析、常见问题和最佳实践,感兴趣的朋友一起看看吧... 目录一、Spring Boot 异常处理的背景与核心概念1.1 为什么需要异常处理?1.2 Spring B