Android单点触控与多点触控切换的问题解决方案

目前网络上有很多关于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     @Override
13     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         //设置显示View
20         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

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值