工作笔记之-GestureDetector手势检测

来到公司,一个需求甩在了脸上——实现手势控制视频音量进度亮度调整。

作为一名合格的代码搬运工,自然先去百度一番,看了看前辈的做法。发现了GestureDetector这一个类。下面我们一起学习一下这一个类。

看一下api,这个类是用来发现各种各样的手势和事件,并且当一个特别的位移事件发生时,GestureDetector.OnGestureListener这个回调将会通知使用者,这个类仅被用来记录一些通过触摸发生的动作事件。

如何使用这个类:

1.为你的控件创建一个GestureDetector实例。

2.需要确保调用了onTouchEvent(MotionEvent)这个方法。这个方法可以确保在事件发生时去回调你的方法。


看一个构造方法

GestureDetector(Context context, GestureDetector.OnGestureListener listener)

Creates a GestureDetector with the supplied listener.  
第一个参数:上下文环境
第二个参数:已经提供的接口。

我们新建一个类,实现OnGestureListener这个接口,重写接口里面的方法。
(如果想要监听少量的手势,继承 GestureDetector.SimpleOnGestureListener会是一个更好的选择。GestureDetector.OnGestureListener是用来监听所有手势


package com.example.gesturedemo;


import android.app.Activity;
import android.content.Context;
import android.media.AudioManager;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.view.ViewTreeObserver;
import android.view.ViewTreeObserver.OnGlobalLayoutListener;
import android.widget.RelativeLayout;


public class MainActivity extends Activity implements OnGestureListener,
OnTouchListener {
private AudioManager audiomanager;
private int maxVolume, currentVolume;
private static final String TAG = "gesture";
private GestureDetector mGestureDetector;
private RelativeLayout relative;
private int width, height;
private boolean firstScroll;


@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGestureDetector = new GestureDetector(this, this);
audiomanager = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
maxVolume = audiomanager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
currentVolume = audiomanager.getStreamVolume(AudioManager.STREAM_MUSIC);
Log.d(TAG, "maxVolume=" + maxVolume);
Log.d(TAG, "currentVolume=" + currentVolume);
relative = (RelativeLayout) findViewById(R.id.relative);
relative.setOnTouchListener(this);
ViewTreeObserver vto = relative.getViewTreeObserver();
vto.addOnGlobalLayoutListener(new OnGlobalLayoutListener() {


@Override
public void onGlobalLayout() {
relative.getViewTreeObserver().removeGlobalOnLayoutListener(
this);
width = relative.getWidth();
height = relative.getHeight();
Log.d(TAG, "width=" + width);
Log.d(TAG, "height=" + height);
}
});


}


@Override
public boolean onDown(MotionEvent e) {
Log.d(TAG, "down");
firstScroll = true;
return true;
}


@Override
public void onShowPress(MotionEvent e) {
// TODO Auto-generated method stub


}


@Override
public boolean onSingleTapUp(MotionEvent e) {
// TODO Auto-generated method stub
return false;
}


@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
float distanceY) {
Log.i(TAG, distanceX + "       ~X");
Log.i(TAG, distanceY + "       ~Y");
Log.i(TAG, e1.getX()+"     e1 X");
Log.i(TAG, e1.getY()+"     e1 Y");
Log.i(TAG, e2.getX()+"     e2 X");
Log.i(TAG, e2.getY()+"     e2 Y");
Log.i(TAG, e2.getX() - e1.getX() + "    2-1   ~ X");
Log.i(TAG, e2.getY() - e1.getY() + "    2-1   ~ Y");
return false;
}


@Override
public void onLongPress(MotionEvent e) {
// TODO Auto-generated method stub
Log.d(TAG, "long");
}


@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
float velocityY) {
// TODO Auto-generated method stub
return false;
}


@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}


}


工作笔记之-GestureDetector手势检测_第1张图片

我们在api中可以看到,实现GestureDetector.OnGestureListener接口需要实现以上的方法。

OnGestureListener有下面的几个动作:

按下(onDown): 刚刚手指接触到触摸屏的那一刹那,就是触的那一下。

抛掷(onFling): 手指在触摸屏上迅速移动,并松开的动作。

长按(onLongPress): 手指按在持续一段时间,并且没有松开。

滚动(onScroll): 手指在触摸屏上滑动。

按住(onShowPress): 手指按在触摸屏上,它的时间范围在按下起效,在长按之前。

抬起(onSingleTapUp):手指离开触摸屏的那一刹那。


想要看方法的一些功能,可以打上log实际体验一下。这里我们具体介绍一下onScroll这个方法。

如上代码所示,我在onScroll方法体里面加了一些log信息

Log.i(TAG, distanceX + "       ~X");
Log.i(TAG, distanceY + "       ~Y");
Log.i(TAG, e1.getX()+"     e1 X");
Log.i(TAG, e1.getY()+"     e1 Y");
Log.i(TAG, e2.getX()+"     e2 X");
Log.i(TAG, e2.getY()+"     e2 Y");
Log.i(TAG, e2.getX() - e1.getX() + "    2-1   ~ X");
Log.i(TAG, e2.getY() - e1.getY() + "    2-1   ~ Y");

运行一下代码,在logcat里分析一下这些打印出来的数据。

工作笔记之-GestureDetector手势检测_第2张图片

这些信息是我的手指在屏幕上从左向右滑动时出现的。

distanceX是一个负数,而且e1.getX()-e2.getX()=distanceX。所以distanceX就是手指开始的x坐标减去手指停下的x坐标。

distanceY和X一样,是手指开始的Y坐标减去手指停下时的Y坐标。

第一组数据分析完,我们看第二组。

这时候我们发现,distanceX的值和e1.getX-e2.getX并不一样。为什么呢,我们观察一下e1的坐标。可以发现这几组数据中e1的坐标没有发生任何变化。

这是不是说明从手指down开始,e1的坐标已经定了下来,发生变化的只是e2的坐标。我们来验证一下,第二组数据e2.getX-e1.getX=12.700371,第一次的distanceX=7.106346。第二次的distanceX=5.5940247.两者相加我们看一下数值,12.7003707。数值基本相同,其中的误差在我们的误差范围内。

这里我们就可以知道,

e1就是手指第一次落下的位置。

e2就是手指滑动过程中不断变换的位置。

distanceX也要重新解释,它代表的是手指滑动过程中的一段段的横向距离。

distanceY代表手指滑动过程中一段段的纵向距离。

如果想要得到滑动的横向总距离,可以用e2.getX-e1.getX获得。

如果想得到滑动的纵向总距离,可以用e2.getY-e1.getY获得。

因为我同时也实现了onTouchListener接口,所以在onTouch这个方法里面调用了mGestureDetector.onTouchEvent(event)这个方法。

如果你没有实现onTouchListener这个接口,那么你需要重写一下Activity类里面的OnTouchEvent这个方法,然后return mGestureDetector.onTouchEvent(event);即可。

如果按照上述做了之后你的onScroll没有被调用,那么你需要在onDown方法里面返回true。


你可能感兴趣的:(工作笔记之-GestureDetector手势检测)