• 41. 【Android教程】Android 手势处理


    作为忠实的 Android 系统用户,你应该会经常用到各种手势:点击、长按、双击、缩放、滑动、拖拽、返回等等,可以说丰富的手势可以让用户更加简洁方便的使用 App,甚至直接影响到 App 的使用体验。这些手势都是系统为我们提供的操作方式,今天来一起看看如何捕捉用户的手势输入。

    1 手势检测工具

    在前面的章节我们讲到过触摸事件:onTouch(),它是一切手势的开始,所以根据onTouch的几种事件类型我们可以判断出用户的各种手势,但是对于一些相对复杂的手势(比如缩放、旋转、双击等)判断起来会比较麻烦。不过这些都不用担心Android 系统为我们提供了一个叫GestureDetector的工具类,通过它我们可以轻松的接收到用户的各种复杂手势。

    GestureDetector的使用方法非常简单,首先创建一个类继承自GestureDetector.SimpleOnGestureListener,然后覆写其中需要监听的事件方法,如下:

    1. GestureDetector mGesture;
    2. mGesture = new GestureDetector(this, new Gesture());
    3. class Gesture extends GestureDetector.SimpleOnGestureListener{
    4. public boolean onSingleTapUp(MotionEvent ev) {
    5. // 处理单击事件
    6. }
    7. public void onLongPress(MotionEvent ev) {
    8. // 处理长按
    9. }
    10. public boolean onScroll(MotionEvent e1, MotionEvent e2, float distanceX,
    11. float distanceY) {
    12. // 处理滑动手势
    13. }
    14. public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX,
    15. float velocityY) {
    16. // 处理快速滚动
    17. }
    18. }

    2 GestureListener 相关事件

    Gesture 支持很多复杂的手势处理,基本上处理手势用它就没错了。这里挑几个最常见的进行详细的讲解,其余的也大同小异。

    • onDown: 触摸事件,同onTouch事件当中的ACTION_DOWN,所有手势的起点
    • onSingleTapUp: 单击
    • onLongPress: 长按
    • onScroll: 滚动
    • onFling: 手指快速滚动,并离开屏幕,在屏幕继续滚动的时候触发

    3 手势的处理方式

    在写好了第 1 小节的代码之后,关键就是去实现事件处理代码了,点击、长按等事件都比较好理解,这里以缩放手势为例讲解一下具体的手势处理逻辑。

    3.1 缩放处理工具类

    缩放的手势处理是通过ScaleGestureDetector来实现的,首先创建一个ScaleGestureDetector

    1. ScaleGestureDetector scaleGestureDetector;
    2. scaleGestureDetector = new ScaleGestureDetector(this, new ScaleListener());

    构造器需要传入两个参数,一个是上下文 context,一个是缩放时间监听器。所以,在此之前我们还需要创建一个ScaleListener,然后覆写OnTouchEvent(MotionEvent e),并且在OnTouchEvent中将触摸事件传递给 ScaleGestureDetector,代码如下:

    1. public boolean onTouchEvent(MotionEvent ev) {
    2. SGD.onTouchEvent(ev);
    3. return true;
    4. }
    5. private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    6. @Override
    7. public boolean onScale(ScaleGestureDetector detector) {
    8. float scale = detector.getScaleFactor();
    9. return true;
    10. }
    11. }

    3.2 手势处理中常用的系统方法

    在处理手势的过程中,我们还会调用一些系统方法来辅助完成事件处理,主要有以下几个:

    • getEventTime():
      获取事件发生的时间戳
    • getFocusX():
      获取当前手势焦点的 X 轴坐标
    • getFocusY():
      获取当前手势焦点的 Y 轴坐标
    • getTimeDelta():
      获取两次缩放时间的时间差
    • isInProgress():
      判断当前是否正处理缩放过程中
    • onTouchEvent(MotionEvent event):
      接收系统触摸事件,并分发到相应的监听器中

    4 手势处理示例

    本节通过GestureDetector完成一个类似微信聊天中的大图缩放功能,即通过双指往外或者向内的手势来控制图片的放大、缩小。

    4.1 编写布局文件

    布局文件非常简单,核心就是一个 ImageView,用来承载我们缩放的目标图片。需要注意的是,这里要将图片的 scaleType设置成“matrix”,用于后续做缩放:

    1. <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    2. xmlns:tools="http://schemas.android.com/tools"
    3. android:layout_width="match_parent"
    4. android:layout_height="match_parent"
    5. android:padding="20dp"
    6. tools:context=".MainActivity">
    7. <TextView
    8. android:id="@+id/textview"
    9. android:layout_width="wrap_content"
    10. android:layout_height="wrap_content"
    11. android:layout_alignParentTop="true"
    12. android:layout_centerHorizontal="true"
    13. android:text="手势处理示例"
    14. android:textSize="35sp" />
    15. <TextView
    16. android:id="@+id/textView"
    17. android:layout_width="wrap_content"
    18. android:layout_height="wrap_content"
    19. android:layout_below="@+id/textview"
    20. android:layout_centerHorizontal="true"
    21. android:text="Android 教程"
    22. android:textColor="#ff7aff24"
    23. android:textSize="35dp" />
    24. <ImageView
    25. android:id="@+id/imageView"
    26. android:layout_width="40dp"
    27. android:layout_height="40dp"
    28. android:layout_below="@+id/textView"
    29. android:layout_alignParentStart="true"
    30. android:layout_alignParentEnd="true"
    31. android:layout_alignParentBottom="true"
    32. android:scaleType="matrix"
    33. android:src="@drawable/avatar" />
    34. </RelativeLayout>

    4.2 手势处理逻辑编写

    手势处理基本遵循上述逻辑,分为 4 步:

    • 第一步: 首先创建一个ScaleListener,覆写onScale方法来接收缩放手势;
    • 第二步: 然后创建ScaleGestureDetector,构造器传入 context 对象及刚刚创建的ScaleListener对象;
    • 第三步: 接着覆写onTouchEvent(MotionEvent ev),调用 ScaleGestureDetector 的onTouchEvent()方法,传入 MotionEvent,这样就把触摸事件传递给了ScaleGestureDetector,后续的整个缩放手势就全权交给ScaleGestureDetector来处理。
    • 第四步: 最后我们只需要在onScale()中完成我们的图片缩放逻辑即可。

    代码如下,整体思路还是比较清晰的:

    1. package com.emercy.myapplication;
    2. import android.app.Activity;
    3. import android.graphics.Matrix;
    4. import android.os.Bundle;
    5. import android.view.MotionEvent;
    6. import android.view.ScaleGestureDetector;
    7. import android.widget.ImageView;
    8. public class MainActivity extends Activity {
    9. private ImageView iv;
    10. private Matrix matrix = new Matrix();
    11. private float scale = 1f;
    12. private ScaleGestureDetector mDetector;
    13. @Override
    14. protected void onCreate(Bundle savedInstanceState) {
    15. super.onCreate(savedInstanceState);
    16. setContentView(R.layout.activity_main);
    17. iv = findViewById(R.id.imageView);
    18. // 第2步:创建缩放手势检测器ScaleGestureDetector,用于检测缩放手势
    19. mDetector = new ScaleGestureDetector(this, new ScaleListener());
    20. }
    21. // 第3步:覆写onTouchEvent,将触摸事件传递给ScaleGestureDetector
    22. public boolean onTouchEvent(MotionEvent ev) {
    23. mDetector.onTouchEvent(ev);
    24. return true;
    25. }
    26. // 第1步:创建缩放监听器,用于接收缩放事件
    27. private class ScaleListener extends ScaleGestureDetector.SimpleOnScaleGestureListener {
    28. @Override
    29. public boolean onScale(ScaleGestureDetector detector) {
    30. // 第4步:实现图片缩放逻辑
    31. scale *= detector.getScaleFactor();
    32. scale = Math.max(0.1f, Math.min(scale, 5.0f));
    33. matrix.setScale(scale, scale);
    34. iv.setImageMatrix(matrix);
    35. return true;
    36. }
    37. }
    38. }

    我们用双指向外或者向内滑动,就可以看到“照骗”会跟随我们的手势而放大/缩小,整个流程非常顺滑无污染,欢迎自行编译体验。

    5 小结

    本节介绍了一个非常强大的手势处理工具——GestureDetector,如果不使用它,我们需要自行监听onTouch事件,然后结合“DOWN”、“MOVE”、“UP”等等各种不同的 onTouch 事件组合起来才能检测出一些复杂的手势,这一切 GestureDetector 都帮助我们实现了。学完这一章,我们只需要按照几个简单的步骤就可以进行复杂手势的监听,从此可以释放双手,来创造更多复杂的事件让用户更加顺滑的使用了。

  • 相关阅读:
    如何更改SonarQube的JDK版本
    【go】异步任务解决方案Asynq实战
    Document类型【2】
    奇舞周刊第493期:Hook 革命!浅谈 React 新 Hook 的未来与思想
    2.1_3进程控制
    dreamweaver作业静态HTML网页设计 大学美食菜谱网页制作教程(web前端网页制作课作业)
    10.12hw
    嵌入式学习笔记(57)LCD如何显示图像
    MySQL详解
    聊一聊Spring 事务的相关操作
  • 原文地址:https://blog.csdn.net/u014316335/article/details/138151344