在Android开发中我们可能需要监听用户的手势:单击、双击、长按、滑动、缩放等,而在View的onTouchEvent只能单纯地对DOWN、MOVE和UP事件作处理,往往需要做出很多判断才能达到想要的效果。所以GestureDetector为我们封装了以上事件的监听。
GestureDetector类提供了两个接口和一个内部类:OnGestureListener,OnDoubleTapListener,SimpleOnGestureListener。
GestureDetector常用的三个构造函数:
GestureDetector gestureDetector = new GestureDetector(GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.OnGestureListener listener);
GestureDetector gestureDetector = new GestureDetector(Context context,GestureDetector.SimpleOnGestureListener listener);
1⃣️ 声明GestureDetector
private GestureDetector mGestureDetector;
2⃣️ 初始化GestureDetector
mGestureDetector = new GestureDetector(this, new GestureDetector.XxxListener() {
//Override方法...
});
3⃣️ 为目标View设置onTouchListener,将GestureDetector的onTouchEvent事件返回
txtShow.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
⚠️ 注意实现OnDoubleTapListener前必须实现OnGestureListener接口。因为初始化GestureDetector时,构造函数不支持OnDoubleTapListener的传入。
只有两种方法设置OnDoubleTapListener,1⃣️ 创建类同时实现两个接口 ,2⃣️ 调用GestureDetector的setOnDoubleTapListener()方法。
该类实现了上面两个接口的实现,通过继承该类可以选择需要监听的函数。
下面通过该例子研究事件的触发顺序。
1⃣️ 首先在XML中添加TextView
2⃣️ 在Activity中按照设置GestureDetector顺序为其添加监听
public class GestureActivity extends BaseActivity {
private TextView txtShow;
private GestureDetector mGestureDetector;
private static final String TAG = "GestureActivity-zz";
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_gesture);
initView();
setListener();
}
private void initView() {
Toolbar toolbar = findViewById(R.id.include).findViewById(R.id.toolbar);
NavigationView nav = findViewById(R.id.nav_view);
DrawerLayout dawer = findViewById(R.id.drawer_layout);
initToolbar(toolbar, nav, dawer);
txtShow = findViewById(R.id.gesture_txt_demo);
}
@SuppressLint("ClickableViewAccessibility")
private void setListener() {
txtShow.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return mGestureDetector.onTouchEvent(event);
}
});
mGestureDetector = new GestureDetector(this, new GestureDetector.OnGestureListener() {
@Override
public boolean onDown(MotionEvent e) {
txtShow.setText("OnDown");
Log.i(TAG, "onDown: ");
return true;
}
@Override
public void onShowPress(MotionEvent e) {
txtShow.setText("onShowPress");
Log.i(TAG, "onShowPress: ");
}
@Override
public boolean onSingleTapUp(MotionEvent e) {
txtShow.setText("onSingleTapUp");
Log.i(TAG, "onSingleTapUp: ");
return true;
}
@Override
public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX, float distanceY) {
txtShow.setText("onScroll," + "x的距离:" + distanceX + ",y的距离:" + distanceY);
Log.i(TAG, "onScroll: ");
return true;
}
@Override
public void onLongPress(MotionEvent e) {
txtShow.setText("onLongPress");
Log.i(TAG, "onLongPress: ");
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
txtShow.setText("onFling," + "x的速度:" + velocityX + ",y的速度" + velocityY);
Log.i(TAG, "onFling: ");
return true;
}
});
// 设置双击接口
mGestureDetector.setOnDoubleTapListener(new GestureDetector.OnDoubleTapListener() {
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
txtShow.setText("onSingleTapConfirmed");
Log.i(TAG, "onSingleTapConfirmed: ");
return true;
}
@Override
public boolean onDoubleTap(MotionEvent e) {
txtShow.setText("onDoubleTap");
Log.i(TAG, "onDoubleTap: ");
return true;
}
@Override
public boolean onDoubleTapEvent(MotionEvent e) {
txtShow.setText("onDoubleTapEvent");
Log.i(TAG, "onDoubleTapEvent: ");
return true;
}
});
}
}
⚠️事件的触发顺序:
1⃣️ 首先该子线程必须有Looper,则如下创建
new Thread(new Runnable() {
@Override public void run() {
Looper.prepare();
final GestureDetector detector = new GestureDetector(MainActivity.this, new
GestureDetector.SimpleOnGestureListener());
//...
}
}).start();
2⃣️ 使用主线程的Looper创建handler传入构造函数
new Thread(new Runnable() {
@Override public void run() {
final Handler handler = new Handler(Looper.getMainLooper());
final GestureDetector detector = new GestureDetector(MainActivity.this, new
GestureDetector.SimpleOnGestureListener() , handler);
// ...
}
}).start();
1.构造函数
ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener)
ScaleGestureDetector(Context context, ScaleGestureDetector.OnScaleGestureListener listener, Handler handler)
2.外部接口和类
interface OnScaleGestureListener
public static class SimpleOnScaleGestureListener implements OnScaleGestureListener
3.3个方法
boolean onScale(ScaleGestureDetector detector) // 缩放被触发。如果返回true表示缩放事件被处理
boolean onScaleBegin(ScaleGestureDetector detector) // 缩放开始,两个手指在屏幕上就会被调用
void onScaleEnd(ScaleGestureDetector detector) // 缩放结束
imgView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
return scaleGestureDetector.onTouchEvent(event);
}
});
scaleGestureDetector = new ScaleGestureDetector(this, new ScaleGestureDetector.OnScaleGestureListener() {
@Override
public boolean onScale(ScaleGestureDetector detector) {
txtShow.setText("focusX = " + detector.getFocusX() + "\n" + "focusY = " + detector.getFocusY()
+ "\n" + "scale = " + detector.getScaleFactor());
return true;
}
@Override
public boolean onScaleBegin(ScaleGestureDetector detector) {
return true;
}
@Override
public void onScaleEnd(ScaleGestureDetector detector) {
}
});
图片缩放例子涉及MATRIX
安卓自定义View进阶-缩放手势检测(ScaleGestureDecetor)