────────────────────────────── 【概念介绍】
-
手势检测简介
Android 通过 MotionEvent 来描述触摸事件,但要识别复杂的手势(如双击、长按、滚动等),直接处理 MotionEvent 较为繁琐。
为此,Android 提供了 GestureDetector 类,它封装了对常见手势的检测逻辑,开发者只需重写 GestureDetector.SimpleOnGestureListener 中的相关回调方法即可。 -
GestureDetector 工作原理
- 在构造自定义 View 时创建一个 GestureDetector 对象,并传入一个 SimpleOnGestureListener 对象。
- 在自定义 View 的 onTouchEvent 方法中,将触摸事件传递给 GestureDetector。
- GestureDetector 根据 MotionEvent 的序列判断具体手势,并回调对应的方法(例如 onDown、onSingleTapUp、onScroll、onFling、onDoubleTap 等)。
- 回调方法中可执行相应操作,并调用 invalidate() 触发重绘,将检测结果显示到界面上。
────────────────────────────── 【完整示例】
下面提供三个完整文件:
Main.kt:
package com.example.myapplication
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
// 加载布局文件 activity_main.xml
setContentView(R.layout.activity_main)
}
}
main.xml:
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent">
<!-- 在布局中引用自定义手势检测 View -->
<com.example.myapplication.CustomGestureView
android:id="@+id/customGestureView"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
</RelativeLayout>
CustomGestureView:
package com.example.myapplication
import android.content.Context
import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.util.AttributeSet
import android.view.GestureDetector
import android.view.MotionEvent
import android.view.View
/**
* CustomGestureView 演示了如何在自定义 View 中使用 GestureDetector 进行手势检测。
*
* 功能说明:
* 1. 实例化 GestureDetector,并重写常见手势的回调方法,如 onDown、onSingleTapUp、
* onDoubleTap、onLongPress、onScroll 和 onFling。
* 2. 在 onTouchEvent 方法中将 MotionEvent 传递给 GestureDetector。
* 3. 在 onDraw 中根据检测到的手势状态绘制文本,显示当前的手势信息。
*/
class CustomGestureView @JvmOverloads constructor(
context: Context,
attrs: AttributeSet? = null,
defStyle: Int = 0
) : View(context, attrs, defStyle) {
// 用于绘制文字显示手势状态
private val paint: Paint = Paint().apply {
color = Color.BLUE
textSize = 50f
isAntiAlias = true
}
// 存放最新检测到的手势信息
private var gestureText: String = "No gesture detected"
// GestureDetector 用于检测手势事件
/*
GestureDetector 是 Android 中的一个类,用于检测各种手势和手势事件。它可以帮助你识别和处理常见的手势,例如点击、长按、双击、滑动等。
GestureDetector.SimpleOnGestureListener 是一个简化的手势监听器
它实现了 GestureDetector.OnGestureListener 接口,并提供了默认的实现
通过使用 GestureDetector 和 SimpleOnGestureListener,你可以轻松地处理常见的手势事件,如点击、长按、滑动等。
单击时显示 "onDown" 和 "onSingleTapUp";
双击时显示 "onDoubleTap";
长按时显示 "onLongPress";
滑动时显示 "onScroll: dx = ... , dy = ...";
快速滑动时显示 "onFling: vx = ... , vy = ..."。
*/
private val gestureDetector: GestureDetector = GestureDetector(context, object : GestureDetector.SimpleOnGestureListener() {
override fun onDown(e: MotionEvent): Boolean {
gestureText = "onDown"
invalidate()
return true
}
override fun onSingleTapUp(e: MotionEvent): Boolean {
gestureText = "onSingleTapUp"
invalidate()
return true
}
override fun onLongPress(e: MotionEvent) {
gestureText = "onLongPress"
invalidate()
}
override fun onScroll(
e1: MotionEvent?,
e2: MotionEvent,
distanceX: Float,
distanceY: Float
): Boolean {
//你可以直接在字符串字面量后调用 .format 方法,将需要替换的参数传入。
gestureText = "onScroll: dx = %.2f, dy = %.2f".format(distanceX, distanceY)
invalidate()
return true
}
override fun onFling(
e1: MotionEvent?,
e2: MotionEvent,
velocityX: Float,
velocityY: Float
): Boolean {
gestureText = "onFling: vx = %.2f, vy = %.2f".format(velocityX, velocityY)
invalidate()
return true
}
override fun onDoubleTap(e: MotionEvent): Boolean {
gestureText = "onDoubleTap"
invalidate()
return true
}
})
override fun onDraw(canvas: Canvas) {
super.onDraw(canvas)
// 绘制背景
canvas.drawColor(Color.LTGRAY)
// 在屏幕中部绘制手势信息
canvas.drawText(gestureText, 50f, height / 2f, paint)
}
override fun onTouchEvent(event: MotionEvent): Boolean {
// 将触摸事件传递给 GestureDetector 处理
return gestureDetector.onTouchEvent(event) || super.onTouchEvent(event)
}
}
────────────────────────────── 【运行效果】
- 运行应用后,你将看到一个灰色背景的屏幕,中央显示 "No gesture detected"。
- 当你触摸屏幕时,不同手势对应的回调方法会被触发,例如:
- 单击时显示 "onDown" 和 "onSingleTapUp";
- 双击时显示 "onDoubleTap";
- 长按时显示 "onLongPress";
- 滑动时显示 "onScroll: dx = ... , dy = ...";
- 快速滑动时显示 "onFling: vx = ... , vy = ..."。
- 每个回调触发时,View 都会调用 invalidate() 重绘,将最新的手势信息显示在屏幕上。