android手势
In this tutorial, we’ll be discussing and implementing Gestures in our Android Application. Gestures can be a little tricky at first. But once mastered, they are really handy.
在本教程中,我们将在Android应用程序中讨论和实现手势。 首先,手势可能会有些棘手。 但是一旦掌握,它们真的很方便。
(Android Gesture Detectors)
The Gesture Detector class is used to detect touch events from the user. The GestureListener supplies the MotionEvent performed by the user.
手势检测器类用于检测来自用户的触摸事件。 GestureListener提供了由用户执行的MotionEvent 。
You can use the GestureDetector.SimpleOnGestureListener class to listen to a subset of gestures.
您可以使用GestureDetector.SimpleOnGestureListener类来侦听手势的子集。
Those gestures include the following:
这些手势包括以下内容:
- onDown
- onScroll
- onSingleTap
- onDoubleTap
- onLongPress
- onFling
Gestures play the MVP role in Animations. They always enhance the user experience.
手势在“动画”中扮演MVP角色。 它们始终可以改善用户体验。
Let’s look at each of the methods available in the SimpleOnGestureListener class:
让我们看一下SimpleOnGestureListener类中可用的每个方法:
-
onDown(MotionEvent e): Notifies when a tap occurs with the down MotionEvent that triggered it.onDown(MotionEvent e):当触发向下的MotionEvent发生点击时通知。 -
onDoubleTap(MotionEvent e): Notifies when a double-tap occurs.onDoubleTap(MotionEvent e):双击出现时通知。 -
onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY): Notifies of a fast swipe event when it occurs with the initial on down MotionEvent and the matching up MotionEvent. We can set the speed threshold of the fling/swipeonFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY):当快速滑动事件发生时,当向下的MotionEvent初始且向上的MotionEvent匹配时,通知该事件。 我们可以设置猛扑/猛击的速度阈值 -
onLongPress(MotionEvent e): Notifies when a long press occurs with the initial on down MotionEvent that trigged it.onLongPress(MotionEvent e):当长按按下时触发的初始onLongPress(MotionEvent e)发生时,通知此事件。 -
onSingleTapConfirmed(MotionEvent e): Notifies when a single-tap occurs.onSingleTapConfirmed(MotionEvent e):通知何时单击。 -
onShowPress(MotionEvent e): This occurs when a user has performed a down MotionEvent and not performed a move or up yet.onShowPress(MotionEvent e):当用户执行了向下MotionEvent但尚未执行上移或上移时,会发生这种情况。
Now in the next section, we’ll be developing a simple Android Application with a Button on which we can perform the above-discussed Gestures.
现在,在下一节中,我们将开发一个带有按钮的简单Android应用程序,可以在其上执行上述手势。
(Project Structure)

Android Gesture Detector Project Structure
Android手势检测器项目结构
(Code)
The code for the activity_main.xml layout is given below:
下面给出了activity_main.xml布局的代码:
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout
xmlns:android="https:///apk/res/android"
xmlns:tools="https:///tools"
xmlns:app="https:///apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context=".MainActivity">
<Button
android:id="@+id/button"
android:layout_width="150dp"
android:layout_height="150dp"
android:text="DO YOUR GESTURES ON ME"
android:textColor="@android:color/white"
android:background="@color/colorPrimary"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</android.support.constraint.ConstraintLayout>The code for the MainActivity.java class is given below:
MainActivity.java类的代码如下:
package com.journaldev.androidgesturedetector;
import android.content.Context;
import .AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = findViewById(R.id.button);
button.setOnTouchListener(new OnSwipeTouchListener(this) {
public void onSwipeTop() {
Toast.makeText(getApplicationContext(), "Swiped top", Toast.LENGTH_SHORT).show();
}
public void onSwipeRight() {
Toast.makeText(getApplicationContext(), "Swiped right", Toast.LENGTH_SHORT).show();
}
public void onSwipeLeft() {
Toast.makeText(getApplicationContext(), "Swiped left", Toast.LENGTH_SHORT).show();
}
public void onSwipeBottom() {
Toast.makeText(getApplicationContext(), "Swiped bottom", Toast.LENGTH_SHORT).show();
}
});
}
class OnSwipeTouchListener implements View.OnTouchListener {
private final GestureDetector gestureDetector;
public OnSwipeTouchListener(Context ctx) {
gestureDetector = new GestureDetector(ctx, new GestureListener());
}
@Override
public boolean onTouch(View v, MotionEvent event) {
return gestureDetector.onTouchEvent(event);
}
private final class GestureListener extends GestureDetector.SimpleOnGestureListener {
private static final int SWIPE_THRESHOLD = 300;
private static final int SWIPE_VELOCITY_THRESHOLD = 300;
@Override
public boolean onDown(MotionEvent e) {
return true;
}
@Override
public boolean onSingleTapConfirmed(MotionEvent e) {
Log.i("TAG", "onSingleTapConfirmed:");
Toast.makeText(getApplicationContext(), "Single Tap Detected", Toast.LENGTH_SHORT).show();
return true;
}
@Override
public void onLongPress(MotionEvent e) {
Log.i("TAG", "onLongPress:");
Toast.makeText(getApplicationContext(), "Long Press Detected", Toast.LENGTH_SHORT).show();
}
@Override
public boolean onDoubleTap(MotionEvent e) {
Toast.makeText(getApplicationContext(), "Double Tap Detected", Toast.LENGTH_SHORT).show();
return true;
}
@Override
public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
boolean result = false;
try {
float diffY = e2.getY() - e1.getY();
float diffX = e2.getX() - e1.getX();
if (Math.abs(diffX) > Math.abs(diffY)) {
if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
if (diffX > 0) {
onSwipeRight();
} else {
onSwipeLeft();
}
result = true;
}
} else if (Math.abs(diffY) > SWIPE_THRESHOLD && Math.abs(velocityY) > SWIPE_VELOCITY_THRESHOLD) {
if (diffY > 0) {
onSwipeBottom();
} else {
onSwipeTop();
}
result = true;
}
} catch (Exception exception) {
exception.printStackTrace();
}
return result;
}
}
public void onSwipeRight() {
}
public void onSwipeLeft() {
}
public void onSwipeTop() {
}
public void onSwipeBottom() {
}
}
}In the above code, returning false instead of true in the methods, would cause the gesture to not work. Especially, the onDown one can cause all gestures to not work, if false.
在上面的代码中,在方法中返回false而不是true会导致手势不起作用。 特别是, onDown可能导致所有手势无效(如果为假)。
The onFling method, there are two things: Swipe Threshold and Velocity threshold.
onFling方法有两件事: 滑动阈值和速度阈值 。
Swipe threshold indicates the difference between the initial and final position of touch in any of the four directions.
滑动阈值指示在四个方向中任何一个方向上触摸的初始位置和最终位置之间的差异。
Velocity threshold indicates how quickly was it swiped to be termed as a Gesture.
速度阈值指示刷卡被称为手势的速度。
The output of the application in action is given below. It doesn’t show the finger movements due to video constraints. Hence, we’ll encourage you to try it yourself from the sample code attached at the end of this tutorial.
实际应用程序的输出如下。 由于视频限制,它没有显示手指的移动。 因此,我们鼓励您自己尝试使用本教程结尾处随附的示例代码进行尝试。

Android Gesture Detector Output
Android手势检测器输出
That brings an end to this tutorial. You can download the project from the link below:
















