博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android单点触控与多点触控切换的问题解决方案
阅读量:4477 次
发布时间:2019-06-08

本文共 10609 字,大约阅读时间需要 35 分钟。

目前网络上有很多关于Android触控(单点触控和多点触控)的文章,不过在中文文档里面,(我)在百度上找不到关于当单点触控和多点触控同时存在时,不停地在单点触控和多点触控之间切换的资料(要么就是只有单点触控的,要么就是只有多点触控的):举个简单的例子,当单点触控事件点为A,多点触控事件点(以两个为例)为A,B,当先点击一点时,则触发单点触控事件A,再同时点击另外一点时则就会切换到多点触控时间A,B,如果这时候抬起事件点A,则会将多点触控事件点B对应到单点触控事件点A,在这个对应关系上面,网上几乎没有什么好用的文档(简言就是A=NEW;A=A,B=NEW;A=B,DEL B;)。因此,我要讲的就是关于单点触控和多点触控之间的切换问题,希望能给大家有一个解决方案的思路吧。

首先,声明基本的MainActivity.java(最基础的东西,不懂可以查看相关文档):

1 package com.veady.touch; 2 /* 3  *  http://www.cnblogs.com/veady/ 4  */ 5 import android.app.Activity; 6 import android.os.Bundle; 7 import android.view.Window; 8 import android.view.WindowManager; 9 10 public class MainActivity extends Activity {11 12     @Override13     protected void onCreate(Bundle savedInstanceState) {14         super.onCreate(savedInstanceState);15         //设置不显示标题16         requestWindowFeature(Window.FEATURE_NO_TITLE);17         //设置全屏18         getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);19         //设置显示View20         setContentView(new TouchSurfaceView(this));21     }22 }

然后,声明TouchSurfaceView.java(处理显示逻辑以及点击事件):

1 package com.veady.touch;  2 /*  3  *  http://www.cnblogs.com/veady/  4  */  5 import android.content.Context;  6 import android.graphics.Canvas;  7 import android.graphics.Color;  8 import android.graphics.Paint;  9 import android.view.MotionEvent; 10 import android.view.SurfaceHolder; 11 import android.view.SurfaceHolder.Callback; 12 import android.view.SurfaceView; 13  14 public class TouchSurfaceView extends SurfaceView implements Callback { 15      16     //声明变量,处理点击事件时绘制圆图形 17     //事件点A 18     private float touchPointAX = 0, touchPointAY = 0, touchPointAR = 100; 19     private boolean touchPointA = false; 20     //事件点B 21     private float touchPointBX = 0, touchPointBY = 0, touchPointBR = 100; 22     private boolean touchPointB = false; 23      24  25     public SurfaceHolder surfaceHolder; 26     //声明画笔 27     public Paint paint;     28     public Canvas canvas; 29      30  31     public TouchSurfaceView(Context context) { 32         super(context); 33         // TODO 自动生成的构造函数存根 34         surfaceHolder = this.getHolder(); 35         surfaceHolder.addCallback(this); 36         //画笔设置 37         paint = new Paint(); 38         paint.setColor(Color.BLACK); 39         paint.setAntiAlias(true); 40         setFocusable(true); 41     } 42  43     @Override 44     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 45         // TODO 自动生成的方法存根 46     } 47  48     @Override 49     public void surfaceCreated(SurfaceHolder arg0) { 50         // TODO 自动生成的方法存根 51          52     } 53  54     @Override 55     public void surfaceDestroyed(SurfaceHolder arg0) { 56         // TODO 自动生成的方法存根     57     } 58  59     //重写点击事件函数 60     public boolean onTouchEvent(MotionEvent event) { 61         //当所有手指都离开屏幕时触发时 62         if (event.getAction() == MotionEvent.ACTION_UP){ 63             touchPointA = false; 64             touchPointB = false; 65         } 66         //当多点触控时第一手指离开屏幕时触发时 67         else if(event.getAction() == MotionEvent.ACTION_POINTER_1_UP){ 68             /* 69              * 注意,这里是错误的地方,因为无法在多点触控时判断先抬起的是那个点的手指 70              */ 71             touchPointA = true; 72         } 73         //当多点触控时第二手指离开屏幕时触发时 74         else if(event.getAction() == MotionEvent.ACTION_POINTER_2_UP){ 75             /* 76              * 注意,这里是错误的地方,因为无法在多点触控时判断后抬起的是那个点的手指,理由同上 77              */ 78             touchPointB = true; 79         }else{ 80             //单点触控时,只绘制A点 81             if(event.getPointerCount() == 1){ 82                 touchPointAX = event.getX(); 83                 touchPointAY = event.getY(); 84                 touchPointA = true; 85             } 86             //多点触控时,同时绘制A,B点 87             else if(event.getPointerCount() == 2){ 88                 touchPointAX = event.getX(0); 89                 touchPointAY = event.getY(0); 90                 touchPointA = true; 91                  92                 touchPointBX = event.getX(1); 93                 touchPointBY = event.getY(1); 94                 touchPointB = true; 95             } 96         } 97         //进行绘制 98         draw(); 99         return true;100     }101     //绘制点函数102     public void draw() {103         try {104             canvas = surfaceHolder.lockCanvas();105             if (canvas != null) {106                 canvas.drawColor(Color.WHITE);107                 //判断进行A,B点绘制108                 if(touchPointA){109                     canvas.drawCircle(touchPointAX, touchPointAY, touchPointAR, paint);110                 }111                 if(touchPointB){112                     canvas.drawCircle(touchPointBX, touchPointBY, touchPointBR, paint);113                 }114             }115         } catch (Exception e) {116         } finally {117             if (canvas != null)118                 surfaceHolder.unlockCanvasAndPost(canvas);119         }120     }121 }

这里展示的是当前网络上一些单点触控和多点触控同时存在的方法,通过此方法在运行时不难发现对于多点触控转单点触控时,会出现明明是单点触控但屏幕上却绘制了了两个点,原因就在于,单点触控没有对多点触控的剩余点进行很好的识别处理。

到这里,有人就可能说了,在多点触控抬起手指时间里面重新刷新屏幕再进行绘制不就能解决问题了吗。但是,这是不可行的,不断的刷新在加入线程之后会导致每次多点触控离开事件操作都会导致屏幕闪屏,影响直接使用,因此,不可取。

那解决方案呢?我认为可以在单点触控开始时记录事件点A的值A'(因为我的单点触控事件是记录在A点之里面的,即A点是单点触控和多点触控都使用的,而B点只有多点触控才使用),然后就可以通过比较A和A'的距离以及A和B的距离来判断遗留的是那个点的手指,从而来进行绘制操作。具体代码如下:

1 package com.veady.touch;  2 /*  3  *  http://www.cnblogs.com/veady/  4  */  5 import android.content.Context;  6 import android.graphics.Canvas;  7 import android.graphics.Color;  8 import android.graphics.Paint;  9 import android.view.MotionEvent; 10 import android.view.SurfaceHolder; 11 import android.view.SurfaceHolder.Callback; 12 import android.view.SurfaceView; 13  14 public class TouchSurfaceView extends SurfaceView implements Callback { 15      16     //声明变量,处理点击事件时绘制圆图形 17     //事件点A 18     private float touchPointAX = 0, touchPointAY = 0, touchPointAR = 100; 19     //新建记忆点A'坐标 20     private float touchPointRemeberX = 0, touchPointRemeberY = 0; 21     private boolean touchPointA = false; 22     //事件点B 23     private float touchPointBX = 0, touchPointBY = 0, touchPointBR = 100; 24     private boolean touchPointB = false; 25     //上次触控为多点触控事件判断 26     private boolean lastTouch = false; 27      28  29     public SurfaceHolder surfaceHolder; 30     //声明画笔 31     public Paint paint;     32     public Canvas canvas; 33      34  35     public TouchSurfaceView(Context context) { 36         super(context); 37         // TODO 自动生成的构造函数存根 38         surfaceHolder = this.getHolder(); 39         surfaceHolder.addCallback(this); 40         //画笔设置 41         paint = new Paint(); 42         paint.setColor(Color.BLACK); 43         paint.setAntiAlias(true); 44         setFocusable(true); 45     } 46  47     @Override 48     public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { 49         // TODO 自动生成的方法存根 50     } 51  52     @Override 53     public void surfaceCreated(SurfaceHolder arg0) { 54         // TODO 自动生成的方法存根 55          56     } 57  58     @Override 59     public void surfaceDestroyed(SurfaceHolder arg0) { 60         // TODO 自动生成的方法存根     61     } 62  63     //重写点击事件函数 64     public boolean onTouchEvent(MotionEvent event) { 65         //当所有手指都离开屏幕时触发时 66         if (event.getAction() == MotionEvent.ACTION_UP){ 67             touchPointA = false; 68             touchPointB = false; 69         } 70         //当多点触控时第一手离开屏幕时触发时 71         else if(event.getAction() == MotionEvent.ACTION_POINTER_1_UP){ 72             //A点坐标记录 73             touchPointRemeberX = touchPointAX; 74             touchPointRemeberY = touchPointAY; 75             //上次为多点触控 76             lastTouch = true; 77         } 78         //当多点触控时第二手离开屏幕时触发时 79         else if(event.getAction() == MotionEvent.ACTION_POINTER_2_UP){ 80             //A点坐标记录 81             touchPointRemeberX = touchPointAX; 82             touchPointRemeberY = touchPointAY; 83             //上次为多点触控 84             lastTouch = true; 85         }else{ 86             //单点触控时,只绘制A点 87             if(event.getPointerCount() == 1){ 88                 //A点坐标获取 89                 touchPointAX = event.getX(); 90                 touchPointAY = event.getY(); 91                  92                 //如果上次为多点触控 93                 if(lastTouch){ 94                     //判断距离点,那个点距离短就认定单点触控留下来的点为那个点 95                     if(Math.pow(touchPointAX - touchPointRemeberX, 2) + Math.pow(touchPointAY - touchPointRemeberY, 2)  96                             > Math.pow(touchPointAX - touchPointBX, 2) + Math.pow(touchPointAY - touchPointBY, 2)){ 97                         /* 98                          * 这里可以写一些按钮的处理函数,不同的按键反馈,暂且以touchPointB = false代替 99                          */100                         touchPointB = false;101                     }else{102                         /*103                          * 这里可以写一些按钮的处理函数,不同的按键反馈,暂且以touchPointB = false代替104                          */105                         touchPointB = false;106                     }107                     lastTouch = false;108                 }109                 110                 touchPointA = true;111             }112             //多点触控时,同时绘制A,B点113             else if(event.getPointerCount() == 2){114                 touchPointAX = event.getX(0);115                 touchPointAY = event.getY(0);116                 touchPointA = true;117                 118                 touchPointBX = event.getX(1);119                 touchPointBY = event.getY(1);120                 touchPointB = true;121             }122         }123         //进行绘制124         draw();125         return true;126     }127     //绘制点函数128     public void draw() {129         try {130             canvas = surfaceHolder.lockCanvas();131             if (canvas != null) {132                 canvas.drawColor(Color.WHITE);133                 //判断进行A,B点绘制134                 if(touchPointA){135                     canvas.drawCircle(touchPointAX, touchPointAY, touchPointAR, paint);136                 }137                 if(touchPointB){138                     canvas.drawCircle(touchPointBX, touchPointBY, touchPointBR, paint);139                 }140             }141         } catch (Exception e) {142         } finally {143             if (canvas != null)144                 surfaceHolder.unlockCanvasAndPost(canvas);145         }146     }147 }

需要注意的是,在多点触控事件在触发抬起事件时,A,B点都是存在的,如果把touchPointB = false;写进去,则会产生闪屏,不信你们可以自己试试。

另外需要说明的是,我这个写来主要是用于游戏操作的多点触控,如图:

左边是一个360°方向摇杆,右侧是四个按键,设定是用户可以同时操作360°方向摇杆和四个按键中的其中一个(有颜色变化),具体的实现我就是用的上面这种方法来识别多点触控和单点触控的切换的。

具体就这么多,如果有人有更好的解决方案,希望能够相互学习下,谢谢。

转载于:https://www.cnblogs.com/veady/p/3757296.html

你可能感兴趣的文章
angularjs 使用angular-sortable-view实现拖拽效果(包括拖动完成后的方法使用)
查看>>
多路复用IO模型
查看>>
利用Python爬虫刷店铺微博等访问量最简单有效教程
查看>>
浅谈软件测试与墨菲定律
查看>>
文件安全复制之 FastCopy
查看>>
强烈推荐美文之《从此刻起,我要》
查看>>
敏捷开发流程
查看>>
[leetCode]Linked List Cycle I+II
查看>>
leetcode中的python学习
查看>>
Zookeeper zkui-zookeeper图形化管理工具
查看>>
CenOS+宝塔(模拟)上线博客项目
查看>>
Codeforces Round #426 (Div. 2) (A B C)
查看>>
The Most Simple Introduction to Hypothesis Testing
查看>>
会了这十种Python优雅的写法,让你工作效率翻十倍,一人顶十人用!
查看>>
在做操作系统实验的一些疑问
查看>>
Log4J日志配置详解
查看>>
NameNode 与 SecondaryNameNode 的工作机制
查看>>
Code obfuscation
查看>>
node.js系列(实例):原生node.js实现接收前台post请求提交数据
查看>>
用python实现矩阵转置
查看>>