触摸,手势操作已经很好的融入了我们的生活。那么
Android
开发中触摸事件要如何捕捉?如何处理?如何识别手势?事件的传递机制又是怎么样的?下面我们将通过一个小例子来进行这方面的学习。
先看效果图
如上图所示,就是一个跟随手指移动的按钮。用来演示我们接下来要说的
onTouch
事件和手势操作。
为了让大家看懂里面的代码,我们来先介绍一下基础知识。
onTouch事件
做什么都好先了解原理以后的工作就会更简单,关于手势以及我们熟悉的
onclick
,
onLongClick
事件都是基于对
onTouch
事件的捕捉和处理。那么在使用手势工具类的前提下我们应该去学习了解基本的
onTouch
事件。
onTouch
常用的以下
4
个事件:
1
、
ACTION_DOWN
:
表示按下了屏幕,第一个执行也是必然执行的方法。
2
、
ACTION_MOVE
:
表示为移动手势,会不断的执行直到触摸停止。
3
、
ACTION_UP
:
表示为离开屏幕,触摸停止的时候执行。
4
、
ACTION_CANCEL
:
表示取消手势,不会由用户产生,而是由程序产生的。
一个
Action_DOWN,
多个
ACTION_MOVE, 1
个
ACTION_UP
,就构成了
Android
中众多的事件。
onTouch的参数
View
受到
Touch
事件的
view
对象
MotionEvent
包含的事件的详细信息,例如触摸点的信息,触摸事件类型的信息等
MotionEvent
的方法例如
getRowX
所描述的都是触摸点的信息。
几个重要方法的说明:
getRowX
:触摸点相对于屏幕的坐标
getX
: 触摸点相对于
view
的坐标
getTop
: 按钮左上角相对于父
view
(
LinerLayout
)的
y
坐标
getLeft
: 按钮左上角相对于父
view
(
LinerLayout
)的
x
坐标
onTouch的返回值
这个部分涉及到事件传递和处理机制,详细的不在此介绍。
作用:
这里的返回值代表的是,对于这个触摸事件
touch
是否已经处理完成。
如果我们设置返回值为
true
代表的是处理完成,这样就不会再传递给下一个对象。也就是说后面的控件或者对象就不会接收到触摸事件了。
反之,后面的对象或控件会在此接收到这个触摸事件并被调用。
实践
在学习基础知识之后,我们来看看如何使用这些来实现一个可以拖动的按钮吧。
思路
这里的主要思路就是在
ACTION_DOWN
按下的第一时间记录下初始的状态,在
ACTION_MOVE
滑动事件中不断的刷新按钮的位置。
为了保证有我们正常理解下的点击事件发生,下面我还加了位置是否移动的判断。
class MyOnTouch implements OnTouchListener{
int[] temp = new int[] { 0, 0 };
Boolean ismove = false;
int downX = 0;
int downY = 0;
@Override
public boolean onTouch(View v, MotionEvent event) {
int eventaction = event.getAction();
int x = (int) event.getRawX();
int y = (int) event.getRawY();
switch (eventaction) {
case MotionEvent.ACTION_DOWN: // touch down so check if the
temp[0] = (int) event.getX();
temp[1] = y - v.getTop();
downX = (int) event.getRawX();
downY = (int) event.getRawY();
ismove = false;
break;
case MotionEvent.ACTION_MOVE: // touch drag with the ball
v.layout(x - temp[0], y - temp[1], x + v.getWidth() - temp[0], y - temp[1] + v.getHeight());
if (Math.abs(downX - x) > 10 || Math.abs(downY - y) > 10)
ismove = true;
break;
case MotionEvent.ACTION_UP:
if (!ismove)
Toast.makeText(MainActivity.this, "你点击了这个按钮", Toast.LENGTH_LONG).show();
break;
}
return false;
}
}
然后在给按钮初始化的时候设置这个事件
[Java]
纯文本查看
复制代码
1
|
touchButton.setOnTouchListener(
new
MyOnTouch());
|
关于手势操作,这里其实说的是
Android
提供的工具类,通过
GestureDetector
类来识别和处理
onTouch
事件,简化使用。
一般用到下面的三个类。
android.view.GestureDetector
手势操作的识别类,通过他来使用下面的识别接口。
android.view.GestureDetector.SimpleOnGestureListener
手势识别的接口类,使用他可以按需重载自己想要的方法,方法多
android.view.GestureDetector.OnGestureListener;
手势识别的类,
SimpleOnGestureListener
接口的父类。使用他需要实现他所有的方法。
方法说明:
OnGestureListener有下面的几个方法:
按下(
onDown
):
在按下时调用。
抛掷(
onFling
):
手指在触摸屏上迅速移动,并松开的动作。
长按(
onLongPress
):
手指按在持续一段时间,并且没有松开。
滚动(
onScroll
):
手指在触摸屏上滑动。
按住(
onShowPress
):
手指按在触摸屏上,它的时间范围在按下起效,在长按之前。
抬起(
onSingleTapUp
):
手指离开触摸屏的那一刹那。
SimpleOnGestureListener比OnGestureListener多出来的方法:
双击(
onDoubleTap
)
双击的第二下
Touch down
时触发
双击事件(
onDoubleTapEvent
)
双击的第二下
Touch down
和
up
都会触发一次,可用
e.getAction()
区分。
实践
好了,学习完了基础知识之后我们来用手势操作的工具类来实现我们的小按钮吧。
下面来实现我们的手势操作内部类。这里我直接实现了
OnGestureListener
接口,为了更好的演示效果。
[Java]
纯文本查看
复制代码
001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
018
019
020
021
022
023
024
025
026
027
028
029
030
031
032
033
034
035
036
037
038
039
040
041
042
043
044
045
046
047
048
049
050
051
052
053
054
055
056
057
058
059
060
061
062
063
064
065
066
067
068
069
070
071
072
073
074
075
076
077
078
079
080
081
082
083
084
085
086
087
088
089
090
091
092
093
094
095
096
097
098
099
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
|
class
MyGesture
implements
OnTouchListener, OnGestureListener {
GestureDetector myGesture =
new
GestureDetector(MainActivity.
this
,
this
);
View view =
null
;
int
[] temp =
new
int
[] {
0
,
0
};
@Override
public
boolean
onTouch(View v, MotionEvent event) {
//这一步只是我的强迫症而已,因为onTouch事件是不断被调用的
if
(view ==
null
)
view = v;
myGesture.onTouchEvent(event);
return
false
;
}
//在按下时调用
@Override
public
boolean
onDown(MotionEvent e) {
temp[
0
] = (
int
) e.getX();
temp[
1
] = ((
int
) e.getRawY()) - view.getTop();
return
false
;
}
//手指在触摸屏上迅速移动,并松开的动作。
@Override
public
boolean
onFling(MotionEvent e1, MotionEvent e2,
float
velocityX,
float
velocityY) {
return
false
;
}
//长按的时候调用
@Override
public
void
onLongPress(MotionEvent e) {
}
//按住然后滑动时调用
@Override
public
boolean
onScroll(MotionEvent e1, MotionEvent e2,
float
distanceX,
float
distanceY) {
int
x = (
int
) e2.getRawX();
int
y = (
int
) e2.getRawY();
view.layout(x - temp[
0
], y - temp[
1
], x + view.getWidth() - temp[
0
], y - temp[
1
] + view.getHeight());
return
false
;
}
// 用户轻触触摸屏,尚未松开或拖动,由一个1个MotionEvent ACTION_DOWN触发
// 注意和onDown()的区别,强调的是没有松开或者拖动的状态
@Override
public
void
onShowPress(MotionEvent e) {
}
// 用户(轻触触摸屏后)松开,由一个1个MotionEvent ACTION_UP触发
@Override
public
boolean
onSingleTapUp(MotionEvent e) {
Toast.makeText(MainActivity.
this
,
"你点击了按钮"
, Toast.LENGTH_LONG).show();
return
false
;
}
}
|
然后在使用的时候给我们的按钮设置进去就好了
[Java]
纯文本查看
复制代码
1
|
touchButton.setOnTouchListener(
new
MyGesture());
|
在内部类的开头初始化我们的
GestureDetector
处理类
[Java]
纯文本查看
复制代码
1
|
GestureDetector myGesture =
new
GestureDetector(MainActivity.
this
,
this
);
|
在
onTouch
方法中调用
GestureDetector
的方法
[Java]
纯文本查看
复制代码
1
|
myGesture.onTouchEvent(event);
|
关于按钮功能的说明:
可以拖动的按钮,这个功能的核心代码是
[Java]
纯文本查看
复制代码
1
|
v.layout(x - temp[
0
], y - temp[
1
], x + v.getWidth() - temp[
0
], y - temp[
1
] + v.getHeight());
|
在滑动事件中调用
[Java]
纯文本查看
复制代码
1
|
view.layout(
int
l,
int
t,
int
r,
int
b)
|
文章还不够详细,若有疑问欢迎提问。
源码下载: