本站文章均为 李华明Himi 原创,转载务必在明显处注明:

转载自【黑米GameDev街区】 原文链接: http://www.himigame.com/android-game/337.html

———————————————————————

很多童鞋说我的代码运行后,点击home或者back后会程序异常,如果你也这样遇到过,那么你肯定没有仔细读完Himi的博文,第十九篇Himi专门写了关于这些错误的原因和解决方法,这里我在博客都补充说明下,省的童鞋们总疑惑这一块;请点击下面联系进入阅读:

【Android游戏开发十九】(必看篇)SurfaceView运行机制详解—剖析Back与Home按键及切入后台等异常处理! 』

——————————————————————-

本文补充:网上很多关于手势文章都说Android 对手势的支持是从SDK 1.6 (也就是 API 4)才开始的,但是我用SDK1.5模拟器也能识别!。(本想测试下更低的SDK的支持效果,但是我没有SDK低于1.5版本的….我手机SDK 2.2的 – -、),所以查了Api 发现:

          android.view.GestureDetector.OnGestureListener;    since api-1 ,

          android.view.GestureDetector;  since api-1 ,

从API来看从api-1开始就已经支持手势和手势监听器了,那么很多说api-4才支持这句话也没错!因为:android.gesture 这个类是从 api-4才开始支持的,这个类输入法手势识别中会用到!so~

                  结论:触摸屏手势识别是从API-1 就开始支持了。 而输入法手势识别是API-4才开始支持的!这里要搞清楚!

对于Android 的手势不光在软件中会经常用到,比如浏览器中的翻页,滚动页面等等;当然其实在我们开发Android游戏的时候加上了Android手势操作更会让游戏增加一个亮点,比如一般的CAG ,PUZ等类型的游戏选择关卡啦、简单背景的移动啦,都可以使用手势来操作即可,类似前段时间很火的《让人愤怒的小鸟!》咳咳、不好意思说错了,是《愤怒的小鸟》,因为总是听群里啊,朋友啊说小鸟出新版本啦,小鸟出PC硬盘版啦! 唉~你说可让人愤怒,其实说实话,小鸟这个游戏确实不错,我所看到的唯一的亮点是这款游戏的创意!说实话,现在的游戏没有做不出来的只有想不出来的好创意、咳咳。回到话题来,那么下面我们来稍微了解下什么是Android 手势!

所谓手势操作,类似跳舞机、EZdancer~这些利用不同动作和音符让人手舞足蹈一样,那么Android这里的手势只是让我们在游戏和软件中的操作有了更多的花样和玩法,根据玩家接触屏幕时间的长短,在屏幕上滑动的距离,按下抬起的时间等进行了包装,其实就是Android 对触屏处理做了包装和处理。

那么在Android中其实有两种手势识别技术。一种是触摸屏手势识别,另一种是输入法手势识别;两者比较起来第二种比较灵活,可以自定义手势,比较high!那么这一节我们先来介绍第一种手势识别:触摸屏手势识别;在下篇博文中我会给童鞋们讲解输入法手势识别

先把两张截图放上来吧:

OK,老方式,先上代码:

MySurfaceView.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174

package com.himi;
import java.util.Vector;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.GestureDetector.OnGestureListener;
import android.view.SurfaceHolder.Callback;
import android.view.View.OnTouchListener;
/**
*@author Himi
*@ Gesture (上文)触摸屏手势识别
*/
public class MySurfaceViewAnimation extends SurfaceView implements Callback,
        Runnable, OnGestureListener, OnTouchListener {
    private Thread th = new Thread(this);
    private SurfaceHolder sfh;
    private Canvas canvas;
    private Paint paint;
    private Bitmap bmp;
    private GestureDetector gd;
    private int bmp_x, bmp_y;
    private boolean isChagePage;
    private Vector<String> v_str;// 备注1
    public MySurfaceViewAnimation(Context context) {
        super(context);
        v_str = new Vector<String>();
        this.setKeepScreenOn(true);
        bmp = BitmapFactory.decodeResource(getResources(),
                R.drawable.himi_dream);
        sfh = this.getHolder();
        sfh.addCallback(this);
        paint = new Paint();
        paint.setAntiAlias(true);
        this.setLongClickable(true);
        // setLongClickable( true )是必须的,因为 只有这样,
        // 我们当前的SurfaceView(view)才能够处理不同于触屏形式;
        // 例如:ACTION_MOVE,或者多个ACTION_DOWN
        this.setOnTouchListener(this);// 将本类绑定触屏监听器
        gd = new GestureDetector(this);
        gd.setIsLongpressEnabled(true);
    }
    public void surfaceCreated(SurfaceHolder holder) {
        // 当系统调用了此方法才创建了view所以在这里才能取到view的宽高!!有些童鞋总是把东西都放在初始化函数里!
        // 线程最好放在这里来启动,因为放在初始化里的画,那view还没有呢,到了提交画布unlockCanvasAndPost的时候就异常啦!
        bmp_x = (getWidth() - bmp.getWidth()) >> 2;
        bmp_y = (getHeight() - bmp.getHeight()) >> 2;
        th.start();
    }
    public void draw() {
        try {
            canvas = sfh.lockCanvas();
            if (canvas != null) {
                canvas.drawColor(Color.WHITE);// 画布刷屏
                canvas.drawBitmap(bmp, bmp_x, bmp_y, paint);
                paint.setTextSize(20);// 设置文字大小
                paint.setColor(Color.WHITE);
                //这里画出一个矩形方便童鞋们看到手势操作调用的函数都是哪些
                canvas.drawRect(50, 30, 175,120, paint);
                paint.setColor(Color.RED);// 设置文字颜色
                if (v_str != null) {
                    for (int i = 0; i < v_str.size(); i++) {
                        canvas.drawText(v_str.elementAt(i), 50, 50 + i * 30,
                                paint);
                    }
                }
            }
        } catch (Exception e) {
            Log.v("Himi", "draw is Error!");
        } finally {
            sfh.unlockCanvasAndPost(canvas);
        }
    }
    @Override
    public void run() {
        // TODO Auto-generated method stub
        while (true) {
            draw();
            try {
                Thread.sleep(100);
            } catch (Exception ex) {
            }
        }
    }
    public void surfaceChanged(SurfaceHolder holder, int format, int width,
            int height) {
    }
    public void surfaceDestroyed(SurfaceHolder holder) {
    }
    // @Override
    // public boolean onTouchEvent(MotionEvent event) {// 备注2
    // return true;
    // }
    @Override
    public boolean onTouch(View v, MotionEvent event) {// 备注3
        if (v_str != null)
            v_str.removeAllElements();
        return gd.onTouchEvent(event);// 备注4
    }
    // --------------以下是使用OnGestureListener手势监听的时候重写的函数---------
    /**
     * @以下方法中的参数解释:
     * @e1:第1个是 ACTION_DOWN MotionEvent 按下的动作
     * @e2:后一个是ACTION_UP MotionEvent 抬起的动作(这里要看下备注5的解释)
     * @velocityX:X轴上的移动速度,像素/秒
     * @velocityY:Y轴上的移动速度,像素/秒
     */
    @Override
    public boolean onDown(MotionEvent e) {
        // ACTION_DOWN
        v_str.add("onDown");
        return false;
    }
    @Override
    // ACTION_DOWN 、短按不移动
    public void onShowPress(MotionEvent e) {
        v_str.add("onShowPress");
    }
    @Override
    // ACTION_DOWN 、长按不滑动
    public void onLongPress(MotionEvent e) {
        v_str.add("onLongPress");
    }
    @Override
    // ACTION_DOWN 、慢滑动
    public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
            float distanceY) {
        v_str.add("onScroll");
        return false;
    }
    @Override
    // ACTION_DOWN 、快滑动、 ACTION_UP
    public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
            float velocityY) {
        v_str.add("onFling");
        //-------备注5----------
        // if(e1.getAction()==MotionEvent.ACTION_MOVE){
        // v_str.add("onFling");
        // }else if(e1.getAction()==MotionEvent.ACTION_DOWN){
        // v_str.add("onFling");
        // }else if(e1.getAction()==MotionEvent.ACTION_UP){
        // v_str.add("onFling");
        // }
        // if(e2.getAction()==MotionEvent.ACTION_MOVE){
        // v_str.add("onFling");
        // }else if(e2.getAction()==MotionEvent.ACTION_DOWN){
        // v_str.add("onFling");
        // }else if(e2.getAction()==MotionEvent.ACTION_UP){
        // v_str.add("onFling");
        // }
        if (isChagePage)
            bmp = BitmapFactory.decodeResource(getResources(),
                    R.drawable.himi_dream);
        else
            bmp = BitmapFactory.decodeResource(getResources(),
                    R.drawable.himi_warm);
        isChagePage = !isChagePage;
        return false;
    }
    @Override
    // 短按ACTION_DOWN、ACTION_UP
    public boolean onSingleTapUp(MotionEvent e) {
        v_str.add("onSingleTapUp");
        return false;
    }
}

补充一下:代码初始化手势的时候有这么一句:gd.setIsLongpressEnabled(true);这个函数标识,如果你设置true的话就是开启了长按键,当你长时间触屏不动就能得到 onLongPress 手势,如果设置false 那么你长时间触屏不移动也得不到这个手势的支持~此函数不设置也默认设置为true

 备注1:

   这里我只是给一些不太熟悉这种定义Vector方式的童鞋简单介绍一下:我们一般定义容器的时候都是直接 Vector vc =new Vector();嗯,没错,但是这种Vector<String>的定义是种泛型定义,那么简单的说下区别,如果Vector vc =new Vector();这种方式装入Object的以后,取的时候是不是要把取出的进行强转一下类型?! 呵呵,而Vector<String>这种定义的时候就表明了这个容器我只装String类型的元素,so~取出的时候也不用再去强转了。

 备注2 :通过测试发现,这里仍然响应触屏时间,即使你把触屏焦点设置成setFocusableInTouchMode(false)也会调用!!!原因是因为我们本类的view绑定了触屏事件监听器,那么肯定会先响应备注3,然后我们备注4这里没有 return true而是直接返给了手势监听器去监听,让监听器找合适的函数来处理用户的手势,也就是说没有标志处理完成,所以我们的重写的onTouchEvent()也会继续去处理!

备注5

这里注释的代码我是在测试两个动作到底是哪两个,因为网上介绍Android手势帖子都疯传说:

第一个是MotionEvent.ACTION_DOWN 第二个是MotionEvent.ACTION_MOVE!那么第一个动作是按下好理解是玩家刚触屏的动作,第二个是move!难道是移动的点都记录下来了??

其实测试结果发现:

第一个是MotionEvent.ACTION_DOWN 第二个是MotionEvent.ACTION_UP!

唉~现在网上的帖子真是各种抄袭~就不能测试下??郁闷! 既然这两个动作一个是按下一个是抬起那就很明确其意义了,我们可以根据

这两个动作知道用户到底滑动的距离等等了,其距离e2.getX()-e1.getX();

总结:

1.触屏后、一直触屏不动、演变顺序:onDown->onShowPress->onLongPress;

2.触屏后、一直触屏慢移动是onScroll/快移动是onFling 、手指离开屏幕;

注意 :触屏后、一直触屏移动,如果手指不离开屏幕一直都是onScroll,不管你移动的速度多快,永远不会是onFling!

Ok,手势虽然挺简单的,但是如果熟练来使用并且加入游戏中肯定让你的Game增色不少~

我这里给出源码:这个实例我只做了一个手势的处理,因为其他的动作都很简单不多说了~OK 各位晚安~

源码下载:   “触屏手势识别GestureTest.rar”       下载地址:  http://vdisk.weibo.com/s/hq3ez

【ANDROID游戏开发十六】ANDROID GESTURE之【触摸屏手势识别】操作!利用触摸屏手势实现一个简单切换图片的功能!...相关推荐

  1. 【Android游戏开发十六】Android Gesture之【触摸屏手势识别】操作!

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/337.html   ...

  2. 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用Android—Tween Animation!

     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigame.com/android-game/331.html 很多童鞋说 ...

  3. 【Android游戏开发十二】(保存游戏数据 [上文])详解SharedPreference 与 FIleInputStream/FileOutputStream将数据存储到SD卡中!

     李华明Himi 原创,转载务必在明显处注明: 转载自 [黑米GameDev街区] 原文链接:  http://www.himigame.com/android-game/327.html 很多童鞋说 ...

  4. Android游戏开发十日通(7)- 开发一个双人游戏

    提要 游戏需要分享才能获得快乐,想想你以前玩过的那些游戏,那些会是真正地存在你婶婶的脑海里?是独自一人躲在被窝里酣战PSP,还是和哥们在网吧一起开黑?是一个人单刷迅龙三连,还是和朋友联机怒刷黄黑龙? ...

  5. 【Android游戏开发十四】深入Animation,在SurfaceView中照样使用Android—Tween Animation!...

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/331.html 之 ...

  6. 【Android游戏开发十八】解放手指,利用传感器开发游戏!

    本站文章均为 李华明Himi 原创,转载务必在明显处注明: 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/android-game/344.html 前 ...

  7. 【Android游戏开发十八】解放手指,利用传感器开发游戏!(本文讲解在SurfaceView中用重力传感器控制圆球的各方向移动)

    本站文章均为 李华明Himi 原创,转载务必在明显处注明:(作者新浪微博: @李华明Himi ) 转载自[黑米GameDev街区] 原文链接: http://www.himigame.com/andr ...

  8. 【安卓开发 】Android初级开发(十二)Android向系统日历中添加事件

    1.首先需要获取权限 <uses-permission android:name="android.permission.READ_CALENDAR" /><us ...

  9. Android游戏开发十日通(6)- 太空大战

    今天要学习的是coscos2d-x官网索引的一篇初级游戏教程.作为小白的入门,再适合不过了. 资源文件下载 工程源码下载 大师的源码 环境: lubuntu 13.10 32bit  Android ...

最新文章

  1. Laravel7使用Auth进行用户认证
  2. 华为接入鸿蒙,华为将发布鸿蒙平板,魅族宣布接入鸿蒙系统
  3. c#split方法拆分为数据_Dexplot:基于pandas,比matplotlib更简单的数据可视化和数据分析工具...
  4. 如何安装vscode网页版_Windows10专业版/企业版如何安装Microsoft store
  5. mysql master 监控_可用于监控 mysql Master Slave 状态的python代码
  6. django 1.8 官方文档翻译: 2-5-10 数据库函数
  7. Openldap 整合windows AD认证
  8. springboot结合mybatis连接数据库
  9. Labview笔记(十)---文件IO (中)---读写 配置文件,XML文件
  10. 串口和并口通信1-概念
  11. 定时任务时间表达式的规则
  12. linux 打印机任务队列,使用Samba和CUPS的打印机队列
  13. 【读书笔记】目标是什么
  14. 静态库、动态库及导入库
  15. 实时Linux内核(PREEMPT_RT)的编译安装以及测试
  16. ElementUI(1):很好的前端开发框架
  17. 优秀logo设计解析_优秀logo设计作品及寓意解析,国外精品logo设计图片分享
  18. web设计与制作|DW故宫景点介绍网页设计制作|web旅游景点网站模板成品|html故宫介绍网页设计制作源码|HTML5期末大作业...
  19. JS获取本机IP的工具类
  20. 什么是事务?事务的特性?

热门文章

  1. Oracle内部错误ORA-07445:[_memcmp()+88] [SIGSEGV]一例
  2. 分布式通信框架 - rmi
  3. 【转】C#解析HTML
  4. 《Excel 职场手册:260招菜鸟变达人》一第 14 招 利用数据验证记录数据录入时间...
  5. Tomcat 的数据库连接池设置与应用
  6. 交叉表的简单实现2:使用前端程序实现
  7. 3.1.3 awk命令用法
  8. 【进阶4-1期】详细解析赋值、浅拷贝和深拷贝的区别
  9. python 笔记 之 sqlalchemy操作数据库-创建表
  10. 根据两点间的经纬度计算距离