在很多应用中我们经常会看到一些不同手势的点击事件,例如QQ的消息列表,我们可以通过左滑消息来选择删除或者置顶或者标记为已读,我们也可以通过右滑拖出QQ菜单。有些应用中还会有长按,双击等手势。但是一般情况下,这些操作的手势都不是很复杂,不会出现什么右击左击,或者三连击这样的手势。因为开发应用的原则就是简单化,让别人可以一看就懂,一看就会。
今天我们就来学习一下Android中手势的操作。在Android中手势的操作使用GestureDetector这个类。
GestureDetector概述
Detects various gestures and events using the supplied MotionEvents. The GestureDetector.OnGestureListener callback will notify users when a particular motion event has occurred. This class should only be used with MotionEvents reported via touch (don’t use for trackball events).
GestureDetector通过MotionEvent类检测不同的手势和事件。在MotionEvent有很多基础的动作监测:ACTION_CANCEL(动作取消), ACTION_DOWN(按下), ACTION_MOVE(移动),ACTION_UP(抬起)等,而手势的操作就是以MotionEvent中这些基本的动作为基础的,通过将这些基本的动作组合从而形成手势。在GestureDetector中有一个GestureDetector.OnGestureListener监听类,这个类都是当手势发生时调用的。
要使用GestureDetector类,我们首先要创建它的对象,我们先来看他的构造器:
注意:GestureDetector(GestureDetector.OnGestureListener listener, Handler handler)和GestureDetector(GestureDetector.OnGestureListener listener)在API level 3以后已经取代,这里不再列出。
- GestureDetector(Context context, GestureDetector.OnGestureListener listener)
传入两个参数,一个是Context的对象,一个是GestureDetector.OnGestureListener的对象。上面已经讲过GestureDetector.OnGestureListener是什么。 - GestureDetector(Context context, GestureDetector.OnGestureListener listener, Handler handler)
前两个不用说了,第三个我查了一下API,原文是这样:”the handler to use for running deferred listener events.”,意思应该是当运行延时的监听对象时使用这个Handler对象。 - GestureDetector(Context context, GestureDetector.OnGestureListener listener, Handler handler, boolean unused)
前三个不用说了吧,最后一个是定义当前有没有被使用。
一般情况下我们都是使用第一个构造器。
GestureDetector中的方法不是很多,有两个是非常重要的,我们这里拿出来说一说,其他的看名字就了解如何使用了: - onGenericMotionEvent(MotionEvent ev)
当我们的手势动作是由GenericMotionEvent动作构成时,我们需要调用这个方法,这样我们定义的手势才可用。 onTouchEvent(MotionEvent ev)
当我们的手势是由MotionEvent 构成时,我们需要调用这个方法,手势才能生效。我们下面来看一下GestureDetector手势是如何定义的?
GestureDetector.SimpleOnGestureListener
创建手势,首先要创建一个GestureDetector对象。创建GestureDetector对象时要传入一个GestureDetector.OnGestureListener对象,所以我们要创建一个GestureDetector.OnGestureListener对象,但是GestureDetector.OnGestureListener是一个interface接口,有人可能会想我们可以创建一个GestureDetector.OnGestureListener的匿名内部类啊,这样是可以,但是要实现GestureDetector.OnGestureListener中的好多方法,这样会使我们代码冗长复杂。API中给我们提供了一个解决的方法,就是通过使用GestureDetector.SimpleOnGestureListener类。
我们看API中对他的描述:A convenience class to extend when you only want to listen for a subset of all the gestures. This implements all methods in the GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener, and GestureDetector.OnContextClickListener but does nothing and return false for all applicable methods.
大体意思是这样的:我们可以通过使用这个类来监听一系列的手势操作,也就是我们可以使用这二个监听器监听多个手势,这个类继承了: GestureDetector.OnGestureListener(手势监听器), GestureDetector.OnDoubleTapListener(双击监听器), and GestureDetector.OnContextClickListener(上下文点击监听器)中的所有方法。
我们来看一下他的方法:
onContextClick(MotionEvent e):上下文点击手势。
onDoubleTap(MotionEvent e):双击手势。
onDoubleTapEvent(MotionEvent e):双击按下和抬起分别产生点击事件手势。
onDown(MotionEvent e):单击手势。
onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):滑动手势,这个要与onScroll区别:onFling是滑动后,事件响应;onScroll是手指滑动时,控件也跟着滑动,同时响应。
onLongPress(MotionEvent e):长按手势。
onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY):拖动手势。
onShowPress(MotionEvent e):按下时响应事件。
onSingleTapConfirmed(MotionEvent e):单击手势。
onSingleTapUp(MotionEvent e):也是单击手势,是单击抬起后响应时间。
手势定义
前面基础差不多都打好了,下面我们来使用下。这里只练习:双击,滑动和拖动的手势操作。
手势定义 ###
定义一个MyButton类继承Button控件。
public class MyButton extends Button {
private GestureDetector mGestureDetector;//定义手势对象
//自定义View的构造器
public MyButton(Context context) {
super(context);
}
public MyButton(Context context, AttributeSet attrs) {
super(context, attrs);
//初始化GestureDetector对象,传入GestureDetector.SimpleOnGestureListener对象,监听多个手势。
mGestureDetector = new GestureDetector(context, new GestureDetector.SimpleOnGestureListener() {
//监听双击手势
@Override
public boolean onDoubleTap(MotionEvent e) {
Log.d("data", "点击了两次按钮! ");
return true;
}
//监听滑动手势
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
if (Math.abs(e2.getX() - e1.getX()) > 0) {
//设置控件滑动的动画
ObjectAnimator.ofFloat(MyButton.this, "translationX", getTranslationX(), getTranslationX() + (e2.getX() - e1.getX())).setDuration(500)
.start();
return true;
}
return super.onFling(e1, e2, velocityX, velocityY);
}
//监听拖动的手势
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
//设置控件跟随手势移动
setTranslationY(getTranslationY() + e2.getY() - e1.getY());
setTranslationX(getTranslationX() + e2.getX() - e1.getX());
return true;
}
});
}
@Override
public boolean onTouchEvent(MotionEvent event) {
//调用此方法,实现手势的监听使用。
mGestureDetector.onTouchEvent(event);
return super.onTouchEvent(event);
}
}
注意:复制代码使用时,onFling方法和onScroll方法不要同时使用,因为效果近似,可能会看不出效果来。使用onFling手势将onScroll方法屏蔽掉,使用onScroll手势时同理。
双击手势:
滑动手势:
拖动手势:
Activity中响应手势事件
如果我们想在Activity中使用双击,滑动,拖动的点击事件,我们需要在MyButton中定义一个点击事件。这里我们以双击为例,在MyButton中添加如下代码:(这里使用到了自定义View中的自定义点击事件知识点,不懂的可以查看《Android 自定义View——自定义点击事件 》这篇博客。)
//这里其实是使用的自定义View的点击事件
public OnDoubleClickListerner onDoubleClickListerner;//定义双击的监听接口对象
//设置获得双击的监听接口对象的set方法。
public void setOnDoubleClickListerner(OnDoubleClickListerner onDoubleClickListerner) {
this.onDoubleClickListerner = onDoubleClickListerner;
}
//创建双击的监听接口
interface OnDoubleClickListerner {
void onDoubleClick(View view);
}
在双击手势中添加:
//监听双击手势
@Override
public boolean onDoubleTap(MotionEvent e) {
if (onDoubleClickListerner != null) {
onDoubleClickListerner.onDoubleClick(MyButton.this);
}
Log.d("data", "点击了两次按钮! ");
return true;
}
这样我们就可以在Activity中使用了:
public class MainActivity extends AppCompatActivity {
private MyButton button;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
button = (MyButton) findViewById(R.id.button);
button.setOnDoubleClickListerner(new MyButton.OnDoubleClickListerner() {
@Override
public void onDoubleClick(View view) {
Log.d("data", "点击了两次按钮! ");
//次此处添加处理代码
}
});
}
}