Android手掌抑制功能的实现

阅读: 评论:0

Android手掌抑制功能的实现

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) {  set();  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) {Measure(widthMeasureSpec, heightMeasureSpec);mViewWidth = Size(widthMeasureSpec);   //获取ViewGroup宽度    mViewHeight = Size(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 = X( );  float eventY = Y( );switch (Action()) {case MotionEvent.ACTION_DOWN: {  veTo(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 = HistorySize();  for (int i = 0; i < historySize; i++) {  float historicalX = HistoricalX(i);  float historicalY = HistoricalY(i);  getDirtyRect(historicalX, historicalY);  mPath.lineTo(historicalX, historicalY);  }  mPath.lineTo(eventX, eventY);  invalidate((int) (mDirtyRect.left - HALF_STROKE_WIDTH), 

本文发布于:2024-01-29 01:32:51,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170646317411756.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

上一篇:opencv手掌跟踪
下一篇:love yy
标签:手掌   抑制   功能   Android
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23