Android开发——用户在屏幕上的手势识别
0. 前言
转载请注明出处:http://blog.csdn.net/seu_calvin/article/details/52462493
Android开发中,我们常常需要获取用户的手势操作事件,从而回调相应的方法完成我们的逻辑业务,在讲手势识别之前,我们有必要了解一下View相关的位置属性。
1. View位置属性
View是一种界面上控件的一种抽象,代表了一个控件。View有很多位置属性。
如图所示,我们的View位置主要由4个定点决定。四个属性分别为left(1),top(2),right(3),bottom(4)。
数字为图上标出的距离。显然这四个属性是相对于父容器来定的,均可以通过get()方法获取。
因此很容易得出View本身的宽高:
width = getRight() - getLeft();
height = getBottom() – getTop();
需要注意的是,View在平移时,上述四个属性值是不会变的。
那么当View平移时,我们用什么属性来描述View相当于屏幕的位置变化?
从Android3.0开始,View新加了几个位置参数,分别为x,y,translationX,translationY。而这四个值是会改变的。
前两者表示相对于父容器View左上角的坐标。后两者表示View左上角相对于父容器的偏移量,默认为0。
2. View的触摸事件
当用户触摸屏幕时,可能发生按下(ACTION_DOWN),移动(ACTION_MOVE)以及抬起(ACTION_UP)三种事件。
下面介绍一些重用的关于触摸事件的数据获取。
2.1 获取事件发生位置
我们可以通过通过getX/Y(相对于当前View左上角的坐标)、getRawX/Y(相对于屏幕左上角的坐标)获取按下或抬起事件发生的位置。
2.2 滑动
对于滑动,这里有一个最小滑动距离的概念。小于该值系统不会认为这是滑动事件。
只要有滑动,必然有滑动速度的概念。我们可以使用VelocityTracker测量滑动速度。
//最小滑动距离
ViewConfiguration.get(getContext()).getScaledTouchSlop();
//获取滑动速度
//在onTouchEvent中使用VelocityTracker
VelocityTracker vt = VelocityTracker.obtain();
vt.addMovement(event);
//速度为100ms内滑动过的像素值,和我们理解的每秒滑动像素值的速度概念不同
//同样的滑动速度,指定时间不一样,速度也不同,另外速度可为负
vt.computeCurrentVelocity(100);
int Vx = (int)vt.getXVelocity();
int Vy = (int)vt.getYVelocity();
//资源回收
vt.clear();
vt.recycle();
2.3 手势检测
在实际开发中,我们完全可以在onTouchEvent()中实现监听点击、抬起、滑动等行为。Android SDK给我们提供了GestureDetector,通过这个类的onTouchEvent(event)方法我们可以识别更多的手势,比如双击事件等等。
GestureDetector的使用示例:
/*
*@author SEU_Calvin
*@date 2010/09/10
*/
private GestureDetector mGestureDetector = new GestureDetector(this, new MyGestureListener());
//长按后可以拖动View
mGestureDetector.setIsLongpressEnabled(false);
@Override
public boolean onTouchEvent(MotionEvent event) {
//接管onTouchEvent方法
return mGestureDetector.onTouchEvent(event);
} class MyGestureListener extends GestureDetector.SimpleOnGestureListener {
@Override
public boolean onDown(MotionEvent ev) {
Log.d("onDown", ev.toString());
return true;
}
//如果手指向左滑,左上角横坐标已经为负了,但是onScroll方法的distanceX为正的,同理右滑distanceX为负,Y轴也一样是反的
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.d("onScroll", e1.toString());
return true;
} @Override
public void onLongPress(MotionEvent ev) {
Log.d("onLongPress", ev.toString());
} @Override
public boolean onSingleTapUp(MotionEvent ev) {
Log.d("onSingleTapUp", ev.toString());
return true;
} @Override
public void onShowPress(MotionEvent ev) {
Log.d("onShowPress ", ev.toString());
} @Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.d("onFling e1 ",e1.toString());
Log.d("onFling e2 ",e2.toString()); return true;
} @Override
public boolean onDoubleTap(MotionEvent e) {
Log.d("onDoubleTap",e.toString());
return super.onDoubleTap(e);
} @Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.d("onSingleTapConfirmed",e.toString());
return super.onSingleTapConfirmed(e);
}
}
上例中的SimpleOnGestureListener类是GestureDetector提供给我们的一个更方便的响应不同手势的类,这个类实现了OnGestureListener,OnDoubleTapListener两个接口。该类是static class,也就是说它实际上是一个外部类,因此我们可以在外部继承这个类,重写里面的手势处理方法。
在看输出结果之前,先对实例中的回调方法进行总结:
表格上已经把各个回调方法解释的很清楚了,这里需要介绍一下为什么双击时不会触发onSingleTapConfirmed,在第一次单击按下时,会给Hanlder发送了一个延时300ms的消息,如果300ms里,发生了第二次单击事件,那就认为是双击事件,并移除之前发送的延时消息。否则判定为触发SingleTapConfirmed。
上例的输出结果(可以自行结合上表进行分析):
(1)单次点击:
(2)长按:
(3)双击:
(4)滑动:
(5)快速滑动:
从滑动和快速滑动的结果来看,GestureDetector都没有“回应”抬起事件的回调。
如果业务逻辑需要我们去“回应”,我们自己在onTouchEvent()中做处理即可。
@Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
mGestureDetector.onTouchEvent(event);
//GestureDetector处理滑动的同时,自己处理抬起UP事件
switch(event.getAction()){
case MotionEvent.ACTION_UP:
//UP事件处理
break;
//...
//其他处理
}
}
至此关于识别用户在屏幕上的手势介绍完毕。
转载请标明出处:http://blog.csdn.net/seu_calvin/article/details/52462493
Android开发——用户在屏幕上的手势识别的更多相关文章
- Android开发--用户定位服务--UserLocation
Android开发--用户定位服务--UserLocation 2013-01-28 08:32:26 我来说两句 作者:BruceZhang 收藏 我要投稿 [java] & ...
- Android 开发中的屏幕适配技术详解
本文主要介绍Android开发中比较头疼繁琐的一个问题-屏幕适配问题.主要从适配原因.基本核心概念.适配方法等方面介详细 介绍从而是的深入或者进一步对Android屏幕适配技术的掌握和理解. 真题园网 ...
- Android开发系列之屏幕密度和单位转换
由于Android的开源性,所以目前市面上面Android手机的分辨率特别多,这样的话就给我适配带来了一定的难度.要想做好适配,我们首先应该明白什么是分辨率.PPI.屏幕大小等概念,还有在不同的屏幕密 ...
- android开发——用户头像
最近,小灵狐得知了一种能够加快修炼速度的绝世秘法,那便是修炼android神功.小灵狐打算用android神功做一个app,今天他的修炼内容就是头像功能.可是小灵狐是个android小白啊,所以修炼过 ...
- android开发中在界面上实现曲线图的几个开源项目
转自:https://wapiknow.baidu.com/question/1959128379041474620?qq-pf-to=pcqq.c2c 几个相关开源项目: 1. MPAndroid ...
- 关于Android开发手机连接不上电脑问题解决方案
1.当然首先你得将手机里的usb debug选项选上,否则lsusb是不会有你的设备的2. lsusb 查看usb设备id3. sudo vim /etc/udev/rules.d/51-androi ...
- Android 开发,你遇上 Emoji 头疼吗?
在 Android 中,如果需要使用的到 Emoji 表情,你会发现在某些设备上,有一些 Emoji 表情会被以豆腐块 "☐" 的形式显示,这是因为当前设备并不支持这个 Emoji ...
- Android开发之改动屏幕方向
有的场景下.我们须要把手机屏幕方向改变,以下是我写的一个样例. xml页面文件: <RelativeLayout xmlns:android="http://schemas.andro ...
- Android开发 retrofit下载与上传
前言 此博客只讲解retrofit下载与上传的使用,其实与其说是retrofit的下载与上传还不如说,依然是Okhttp的下载与上传.如果你需要了解retrofit入门请查看这篇博客(此博客不在详细讲 ...
随机推荐
- C 碎片八 结构体&枚举&联合
一.结构体 1, 结构体定义 结构体类型的定义:任意数据类型变量的集合.用于描述一个具体的事物的信息,在C语言中描述一件事物一般都是用结构体 声明结构体类型的格式: struct 结构体名 {成员列 ...
- Go 微服务实践
http://www.open-open.com/lib/view/open1473391214741.html
- 常见的生成全局唯一id有哪些?他们各有什么优缺点?
分布式系统中全局唯一id是我们经常用到的,生成全局id方法由很多,我们选择的时候也比较纠结.每种方式都有各自的使用场景,如果我们熟悉各种方式及优缺点,使用的时候才会更方便.下面我们就一起来看一下常见的 ...
- java 基础 02 数据类型、运算符、分支结构
内容: (1)数据类型 (2)运算符 (3)分支结构 1.数据类型 java语言中的基本数据类型:byte.short.int.long.float.double.boolean.char. 1.1布 ...
- The sventh day
call it a day 是个相当古老的习惯用语,沿用至今已经有一百五十多年了,但是人民仍然常常用到她. call it a day 可不是“叫一天”的意思哦, 这里是收工的,下班的意思 I thi ...
- redis空间键详解
前言 redis的空间键通知是在2.8.0版本以后加入的,客户端通过发布订阅的方式,订阅某个频道,接收通过某种方式影响redis中数据的事件. 目录: 1.空间键事件分类 2.如何启用redis的空间 ...
- 工作中遇到的有关echarts地图和百度地图的问题
工作中遇到的有关echarts地图和百度地图的问题 *** 前言:在做项目中需要制作一个场景是左边是柱状图,右边是地图,地图上悬浮一个按钮可以切换echarts地图和百度地图.*** 功能: 在点击左 ...
- DB错误代码大全
db2错误代码大全 sqlcode sqlstate 说明000 00000 SQL语句成功完成01xxx SQL语句成功完成,但是有警告+012 01545 未限定的列名被解释为一个有相互关系的引 ...
- Spring之IOC核心模块详解
Spring IOC简述 IOC称为控制反转,也有一种说法叫DI(依赖注入).IOC也是spring最核心的模块,Spring的所有工作几乎都围绕着IOC展开. 什么是控制反转呢?简单的说,控制反转就 ...
- HDU 3697 Selecting courses 选课(贪心)
题意: 一个学生要选课,给出一系列课程的可选时间(按分钟计),在同一时刻只能选一门课程(精确的),每隔5分钟才能选一次课,也就是说,从你第一次开始选课起,每过5分钟,要么选课,要么不选,不能隔6分钟再 ...