144.手势检测 (Gesture Detection) 【view接受事件】

────────────────────────────── 【概念介绍】

  1. 手势检测简介
    Android 通过 MotionEvent 来描述触摸事件,但要识别复杂的手势(如双击、长按、滚动等),直接处理 MotionEvent 较为繁琐。
    为此,Android 提供了 GestureDetector 类,它封装了对常见手势的检测逻辑,开发者只需重写 GestureDetector.SimpleOnGestureListener 中的相关回调方法即可。

  2. 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)
    }
}

────────────────────────────── 【运行效果】

  1. 运行应用后,你将看到一个灰色背景的屏幕,中央显示 "No gesture detected"。
  2. 当你触摸屏幕时,不同手势对应的回调方法会被触发,例如:
    • 单击时显示 "onDown" 和 "onSingleTapUp";
    • 双击时显示 "onDoubleTap";
    • 长按时显示 "onLongPress";
    • 滑动时显示 "onScroll: dx = ... , dy = ...";
    • 快速滑动时显示 "onFling: vx = ... , vy = ..."。
  3. 每个回调触发时,View 都会调用 invalidate() 重绘,将最新的手势信息显示在屏幕上。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值