应用场景:
(1)左右上下滑动屏幕的事件监听。比如,上拉弹出自定义的底部布局之类的,换页之类的等等。
(2)画一些不规则的几何图形。
执行顺序:
- 1.手指触碰屏幕时,触发MotionEvent事件!
- 2.该事件被OnTouchListener监听,可在它的onTouch()方法中获得该MotionEvent对象!
- 3.通过GestureDetector转发MotionEvent对象给OnGestureListener
- 4.我们可以通过OnGestureListener获得该对象,然后获取相关信息,以及做相关处理!
我们来看下上述的三个类都是干嘛的: MotionEvent: 这个类用于封装手势、触摸笔、轨迹球等等的动作事件。 其内部封装了两个重要的属性X和Y,这两个属性分别用于记录横轴和纵轴的坐标。 GestureDetector: 识别各种手势。 OnGestureListener: 这是一个手势交互的监听接口,其中提供了多个抽象方法, 并根据GestureDetector的手势识别结果调用相对应的方法。
功能代码:
package com.deepreality.summarizetestdemo;
import android.content.Context;
import android.os.Bundle;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.widget.Toast;
public class GestureActivity extends AppCompatActivity {
private Context mContext;
private static String TAG = "GestureListener---";
private MyGestureListener myGestureListener;
private GestureDetector gestureDetector;
private static int MIN_MOVE = 200;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture);
baseDataInit();
bindViews();
viewsAddListener();
}
@Override
protected void onDestroy() {
super.onDestroy();
}
private void baseDataInit() {
mContext = this;
myGestureListener = new MyGestureListener();
gestureDetector = new GestureDetector(mContext, myGestureListener);
}
private void bindViews() {
}
private void viewsAddListener() {
}
@Override
public boolean onTouchEvent(MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
class MyGestureListener implements GestureDetector.OnGestureListener {
@Override
public boolean onDown(MotionEvent e) {
Log.e(TAG, "onDown:按下");
return false;
}
@Override
public void onShowPress(MotionEvent e) {
Log.e(TAG, "onShowPress:手指按下一段时间,但是还没到长按");
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
Log.e(TAG, "onSingleTapUp:手指离开屏幕的一瞬间");
return false;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
Log.e(TAG, "onScroll:在屏幕上滑动");
return false;
}
@Override
public void onLongPress(MotionEvent e) {
Log.e(TAG, "onLongPress:手指长按屏幕");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
Log.e(TAG, "onFling:迅速滑动并松开");
if (e1.getY() - e2.getY() > MIN_MOVE) {
Toast.makeText(mContext, "上拉操作", Toast.LENGTH_SHORT).show();
} else if (e1.getY() - e2.getY() < MIN_MOVE) {
Toast.makeText(mContext, "下拉操作", Toast.LENGTH_SHORT).show();
}
Log.e("e1-Y", e1.getY() + "");
Log.e("e2-Y", e2.getY() + "");
return true;
}
}
}
特别注意:
这里用到的是OnGestureListener,需要实现该接口的所有方法,我这边如果仅仅使用滑动操作,显然不太合理。那么怎么处理呢?使用SimpleOnGestureListener即可,需要哪个,就实现哪个方法。
附加:
如何在屏幕画一些不规则图形?比如,银行常用的电子签名功能。
这里用到的是:GestureOverlayView(手势编辑组件)
如何使用呢?
(1)布局文件:
<android.gesture.GestureOverlayView
android:id="@+id/GestureComponent_GOVGesture"
android:layout_width="match_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:gestureColor="@color/colorBlack"
android:gestureStrokeType="multiple"></android.gesture.GestureOverlayView>
(2)获取组件并进行相关设置:
//设置手势编辑组件
//手势的颜色
GOVGesture.setGestureColor(getResources().getColor(R.color.colorBlack));
//手势的粗细
GOVGesture.setGestureStrokeWidth(5);
/*手势绘制完成后淡出屏幕的时间间隔,即绘制完手指离开屏幕后相隔多长时间手势从屏幕上消失;
* 可以理解为手势绘制完成手指离开屏幕后到调用onGesturePerformed的时间间隔
* 默认值为420毫秒,这里设置为2秒
*/
GOVGesture.setFadeOffset(2000);
(3)添加手势编辑完成监听事件
GOVGesture.addOnGesturePerformedListener(this);
(4)通过手势对象获取ImageView所需的Bitmap对象。
//给ImageView赋值手势
bitmap = gesture.toBitmap(100, 100, 10, getResources().getColor(R.color.colorBlack));
ivGesture.setImageBitmap(bitmap);
如何保存和比对手势呢?
(1)保存手势
//文件对应的手势库(保存)
GestureLibrary gestureLib = GestureLibraries.fromFile("/mnt/sdcard/mygestures");
gestureLib.addGesture(etName.getText().toString(), gesture);
gestureLib.save();
(2)比对手势
第一步:
//加载本地手势库
GestureLibrary gestureLibrary = GestureLibraries.fromFile("mmt/sdcard/mygestures");
if (gestureLibrary.load()) {
Toast.makeText(mContext, "手势库加载成功", Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(mContext, "手势库加载失败", Toast.LENGTH_SHORT).show();
}
第二步:
在GesturePerformedListener接口方法OnGesturePerformed里进行识别操作:
//识别用户刚绘制的手势
ArrayList<Prediction> predictions = gestureLibrary.recognize(gesture);
ArrayList<String> result = new ArrayList<String>();
//遍历所有找到的Prediction对象
for (Prediction prediction : predictions) {
if (prediction.score > 2.0) {
result.add("与手势【" + prediction.name + "】相似度为" + prediction.score);
}
}
if (result.size() > 0) {
ArrayAdapter<Object> adapter = new ArrayAdapter<Object>(mContext,
android.R.layout.simple_dropdown_item_1line, result.toArray());
new AlertDialog.Builder(mContext).setAdapter(adapter, null).setPositiveButton("确定", null).show();
}else{
Toast.makeText(mContext,"无法找到匹配的手势!", Toast.LENGTH_SHORT).show();
}
对了,不要忘记添加用户权限哦!
附加:如何在Fragment中添加监听OnTouchEvent。
1、在Fragment的父Activity中添加接口
/** 保存MyTouchListener接口的列表 */ private ArrayList<MyTouchListener> myTouchListeners = new ArrayList<>(); /** 提供给Fragment通过getActivity()方法来注册自己的触摸事件的方法 */ public void registerMyTouchListener(MyTouchListener listener) { myTouchListeners.add(listener); } /** 提供给Fragment通过getActivity()方法来取消注册自己的触摸事件的方法 */ public void unRegisterMyTouchListener(MyTouchListener listener) { myTouchListeners.remove(listener); } @Override public boolean dispatchTouchEvent(MotionEvent ev) { for (MyTouchListener listener : myTouchListeners) { listener.onTouchEvent(ev); } return super.dispatchTouchEvent(ev); } public interface MyTouchListener { /** onTouchEvent的实现 */ boolean onTouchEvent(MotionEvent event); }
2、在相应的Fragment中注册,取消注册监听接口
/** 触摸事件的注册 */ ((MainActivity)this.getActivity()).registerMyTouchListener(myTouchListener);
/** 触摸事件的取消注册 */ ((MainActivity)this.getActivity()).unRegisterMyTouchListener(myTouchListener);
/** 接收MainActivity的Touch回调的对象,重写其中的onTouchEvent函数 */ MainActivity.MyTouchListener myTouchListener = new MainActivity.MyTouchListener() { @Override public boolean onTouchEvent(MotionEvent event) { //处理手势事件(根据个人需要去返回和逻辑的处理) return gestureDetector.onTouchEvent(event); } }; class MyGestureListener extends GestureDetector.SimpleOnGestureListener { @Override public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) { if (e1.getY() - e2.getY() > 20) { FABtnWrite.setVisibility(View.GONE); } else if (e1.getY() - e2.getY() < 20) { FABtnWrite.setVisibility(View.VISIBLE); } return true; } }