文章目录

  • 一、简介
  • 二、概述
    • (一)安卓触摸事件概述
      • 1、触摸分类
        • (1)单点触摸
        • (2)多点触摸
      • 2、触摸动作
      • 3、触摸监听器
      • 4、触摸方法
      • 5、触点个数与坐标
      • 6、安卓触摸事件处理机制
    • (二)案例演示:通过单点触摸移动米老鼠
      • 1、创建安卓应用
      • 2、准备图片素材
      • 3、字符串资源文件
      • 4、主布局资源文件
      • 5、主界面类实现功能
      • 6、启动应用,查看效果
      • 7、修改主界面类
      • 8、重启应用,查看效果
    • (三)案例演示:通过多点触摸缩放米老鼠
      • 1、创建安卓应用
      • 2、准备图片素材
      • 3、字符串资源文件
      • 4、主布局资源文件
      • 5、主界面类实现功能
      • 6、运行程序,查看结果

一、简介

  • 在Android系统中,触摸是用户最常用,最基础的交互方式,只有弄通触摸事件在系统中的传递处理机制才能更好地增强用户的交互体验。触摸事件是安卓应用十分常用的事件,可以分为单点触摸和多点触摸。

二、概述

(一)安卓触摸事件概述

1、触摸分类

(1)单点触摸

  • 单点触控,只能识别和支持每次一个手指的触控、点击,若同时有两个以上的点被触碰,就不能做出正确反应。很多医院、图书馆等的大厅都有这种触控技术的电脑,支持触摸屏的手机、MP3、数码相机也多采用这种单点触控技术。

(2)多点触摸

  • 多点触控(又称多重触控、多点感应、多重感应,英文MultitouchMulti-Touch)是采用人机交互技术与硬件设备共同实现的技术,能在没有传统输入设备(如鼠标、键盘等)。下进行计算机的人机交互操作。多点触摸技术,能构成一个触摸屏(屏幕,桌面,墙壁等)或触控板,都能够同时接受来自屏幕上多个点进行计算机的人机交互操作。

2、触摸动作

动作 常量
按下 MotionEvent.ACTION_DOWN
移动 MotionEvent.ACTION_MOVE
放开 MotionEvent.ACTION_UP

3、触摸监听器

  • 触摸监听器 - onTouchListener - 接口

4、触摸方法

  • onTouch()抽象 方法里,我们可以根据不同动作编写不同事件处理代码。

5、触点个数与坐标

  • 通过MotionEvent对象的getX()getY()方法可以获得触摸点的坐标。如果是多点触摸,通过getPointerCount()获取触点个数,然后通过getX(pointerIndex)getY(pointerIndex)获得某个触点的坐标。

6、安卓触摸事件处理机制

  • 触摸事件从view树的根节点开始一直传递到最下层,直到某个onTouchEvent()接收处理此事件。每个部分对触摸事件的处理过程如下:
  • Activity的处理过程: Activity.dispatchTouchEvent()最先被调用,其作用是调用RootView(通常是一个ViewGroup)dispatchTouchEvent(),即负责分发事件。ViewGroup中的dispatch会调用其他孩子的dispatchTouchEvent()。注意:Activity中的onTouchEvent()是整个View的触摸事件传递链条的终点,不过前提是整个过程中没有view的touchEvent对此事件感兴趣。
  • View的处理过程: 检查是否有TouchListener()注册在这个View中,如果有则查看其是否想要消费此次事件,如果不消费事件,那么接下来该View的onTouchEvent()就要被调用了,如果未返回true,事件就会返回视图树的上一层。
  • ViewGroup的处理过程: 根据触摸发生的位置来判断哪些孩子可能会触发触摸事件,如果有重叠部分则按照被加入到ViewGroup中顺序的逆序来依次处理。ViewGroup可以引发一个中断(onInterceptTouchEvent())来强制把事件交给自己处理,当子视图的事件被剥夺时,子视图会收到ACTION_CANCEL事件,子视图可以用requestDisallowTouchIntercept()方法来屏蔽这个事件。
  • 由此可见,Touch事件是层层向下传递的,如果某个视图接收了此事件则接下来的视图就无法再次接收,但ViewGroup可以强制从子视图手中剥夺一个触摸事件。

(二)案例演示:通过单点触摸移动米老鼠

1、创建安卓应用

  • 基于Empty Activity模板创建安卓应用 - MoveMickeyByTouch

  • 单击【Finish】按钮

2、准备图片素材

  • 将背景图片与米老鼠图片,拷贝到drawable目录里

3、字符串资源文件

  • 字符串资源文件 - strings.xml
<resources><string name="app_name">通过触摸移动米老鼠</string>
</resources>

4、主布局资源文件

  • 主布局资源文件 - activity_main.xml

  • 将约束布局改成线性布局,再添加一个图像控件显示米老鼠

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/root"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/background"  android:orientation="vertical"tools:context=".MainActivity"><ImageViewandroid:id="@+id/iv_mickey"android:layout_width="100dp"android:layout_height="120dp"android:scaleType="fitXY"android:src="@drawable/mickey" />
</LinearLayout>
  • 查看预览效果

5、主界面类实现功能

  • 主界面类 - MainActivity

  • 声明变量和常量

  • 通过资源标识符获取控件实例

  • 让根布局获取焦点

  • 获取米老鼠图像控件的布局参数

  • 给线性根布局注册触摸监听器

  • 查看完整源代码

package net.hw.move_mickey_by_touch;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {private LinearLayout root; // 线性根布局private ImageView ivMickey; // 米老鼠图像控件private LinearLayout.LayoutParams layoutParams; // 布局参数private static final String TAG = "move_mickey_by_touch"; // 标记常量@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 利用布局资源文件设置用户界面setContentView(R.layout.activity_main);// 通过资源标识符获取控件实例root = findViewById(R.id.root);ivMickey = findViewById(R.id.iv_mickey);// 让根布局获取焦点root.setFocusable(true);root.requestFocus();// 获取米老鼠图像控件的布局参数layoutParams = (LinearLayout.LayoutParams) ivMickey.getLayoutParams();// 给线性根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件代码root.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// 根据不同触摸动作执行不同操作switch (event.getAction()) {case MotionEvent.ACTION_DOWN: // 0, 触点按下// 调试信息输出触点坐标Log.d(TAG, "ACTION_DOWN(" + event.getX() + ", " + event.getY() + ")");break;case MotionEvent.ACTION_MOVE: // 2, 触点移动// 调试信息输出触点坐标Log.d(TAG, "ACTION_MOVE(" + event.getX() + ", " + event.getY() + ")");break;case MotionEvent.ACTION_UP: // 1, 触点放开// 调试信息输出触点坐标Log.d(TAG, "ACTION_UP(" + event.getX() + ", " + event.getY() + ")");break;}// 根据变化的触点坐标来更新米老鼠图像控件的布局参数layoutParams.leftMargin = (int) event.getX();layoutParams.topMargin = (int) event.getY();// 重新设置米老鼠图像控件的布局参数ivMickey.setLayoutParams(layoutParams);return true; // 设置为true,三个事件:down-->move-->up才会依次执行}});}
}

6、启动应用,查看效果

  • 启动后,米老鼠在屏幕左上角

  • 在模拟器屏幕上,按下鼠标,移动鼠标,放开鼠标,之后在LogCat里可以看到上述三种动作的位置坐标

  • 录屏演示单点触摸移动米老鼠

  • 从录屏动画可以看到,移动鼠标,确实可以让米老鼠跟着动起来,但是有一个体验不好,触点是米老鼠的左上角,怎么才能让触点是米老鼠的中央呢?

  • 重启应用,查看效果

7、修改主界面类

  • 不采用图像控件的布局参数,直接调用图像控件的setX()setY()方法,分别传入触点横坐标event.getX()和纵坐标event.getY(),如果希望触点在米老鼠控件中央,那么分别传入event.getX() - ivMickey.getWidth() / 2与event.getY() - ivMickey.getHeight() / 2
package net.hw.move_mickey_by_touch;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {private LinearLayout root; // 线性根布局private ImageView ivMickey; // 米老鼠图像控件private static final String TAG = "move_mickey_by_touch"; // 标记常量@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 利用布局资源文件设置用户界面setContentView(R.layout.activity_main);// 通过资源标识符获取控件实例root = findViewById(R.id.root);ivMickey = findViewById(R.id.iv_mickey);// 让根布局获取焦点root.setFocusable(true);root.requestFocus();// 给线性根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件代码root.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// 根据不同触摸动作执行不同操作switch (event.getAction()) {case MotionEvent.ACTION_DOWN: // 0, 触点按下// 调试信息输出触点坐标Log.d(TAG, "ACTION_DOWN(" + event.getX() + ", " + event.getY() + ")");break;case MotionEvent.ACTION_MOVE: // 2, 触点移动// 调试信息输出触点坐标Log.d(TAG, "ACTION_MOVE(" + event.getX() + ", " + event.getY() + ")");break;case MotionEvent.ACTION_UP: // 1, 触点放开// 调试信息输出触点坐标Log.d(TAG, "ACTION_UP(" + event.getX() + ", " + event.getY() + ")");break;}// 设置米老鼠图像控件的坐标ivMickey.setX(event.getX() - ivMickey.getWidth() / 2);ivMickey.setY(event.getY() - ivMickey.getHeight() / 2);return true; // 设置为true,三个事件:down-->move-->up才会依次执行}});}
}

8、重启应用,查看效果

  • 移动米老鼠,可以看到触点在米老鼠中央

(三)案例演示:通过多点触摸缩放米老鼠

1、创建安卓应用

  • 基于Empty Activity模板创建安卓应用 - ZoomMickeyByTouch

  • 单击【Finish】按钮

2、准备图片素材

  • 将背景图片与米老鼠图片,拷贝到drawable目录里

3、字符串资源文件

  • 字符串资源文件 - strings.xml
<resources><string name="app_name">通过多点触摸缩放米老鼠</string>
</resources>

4、主布局资源文件

  • 主布局资源文件 - activity_main.xml

  • 将约束布局改成线性布局,再添加一个图像控件显示米老鼠

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:id="@+id/root"android:layout_width="match_parent"android:layout_height="match_parent"android:background="@drawable/background"android:orientation="vertical"tools:context=".MainActivity"><ImageViewandroid:id="@+id/iv_mickey"android:layout_width="100dp"android:layout_height="120dp"android:scaleType="fitXY"android:src="@drawable/mickey" />
</LinearLayout>
  • 查看预览效果

5、主界面类实现功能

  • 主界面类 - MainActivity

  • 声明变量

  • 通过资源标识符获取控件实例

  • 让根布局获取焦点

  • 获取米老鼠图像控件的布局参数

  • 给根布局注册触摸监听器请添加图片描述

  • 查看完整代码

package net.hw.zoom_mickey_by_touch;import androidx.appcompat.app.AppCompatActivity;import android.os.Bundle;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;
import android.widget.LinearLayout;public class MainActivity extends AppCompatActivity {private LinearLayout root; // 线性根布局private ImageView ivMickey; // 米老鼠图像控件private float x1, y1; // 第一个触点的坐标private float x2, y2; // 第二个触点的坐标private float nextX1, nextY1; // 第一个触点下一次的坐标private float nextX2, nextY2; // 第二个触点下一次的坐标private float distance; // 两个触点之间的距离private float nextDistance; // 两个触点之间下一次的距离private LinearLayout.LayoutParams layoutParams; // 布局参数@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 利用布局资源文件设置用户界面setContentView(R.layout.activity_main);// 通过资源标识符获取控件实例root = findViewById(R.id.root);ivMickey = findViewById(R.id.iv_mickey);// 让根布局获取焦点root.setFocusable(true);root.requestFocus();// 获取米老鼠图像控件的布局参数layoutParams = (LinearLayout.LayoutParams) ivMickey.getLayoutParams();// 给根布局注册触摸监听器,实现触摸监听器接口,编写触摸事件方法root.setOnTouchListener(new View.OnTouchListener() {@Overridepublic boolean onTouch(View v, MotionEvent event) {// 判断触点个数if (event.getPointerCount() == 1) { // 单点触摸 - 移动米老鼠if (event.getAction() == MotionEvent.ACTION_MOVE) {// 根据变化的触点坐标来更新米老鼠图像控件的布局参数layoutParams.leftMargin = (int) (event.getX() - ivMickey.getWidth() / 2);layoutParams.topMargin = (int) (event.getY() - ivMickey.getHeight() / 2);}} else if (event.getPointerCount() == 2) { // 两点触摸 - 缩放米老鼠// 判断触点动作switch (event.getAction()) {case MotionEvent.ACTION_DOWN: // 触点按下// 获取第一个触点的坐标x1 = event.getX(0);y1 = event.getY(0);// 获取第二个触点的坐标x2 = event.getX(1);y2 = event.getY(1);// 计算两个触点之间的距离distance = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));break;case MotionEvent.ACTION_MOVE: // 触点移动// 获取第一个触点下一次的坐标nextX1 = event.getX(0);nextY1 = event.getY(0);// 获取第二个触点下一次的坐标nextX2 = event.getX(1);nextY2 = event.getY(1);// 计算两个触点之间下一次的距离nextDistance = (float) Math.sqrt((nextX1 - nextX2) * (nextX1 - nextX2) + (nextY1 - nextY2) * (nextY1 - nextY2));break;case MotionEvent.ACTION_UP: // 触点放开break;}// 修改米老鼠图像控件的布局参数if (nextDistance > distance) { // 放大图片if (layoutParams.width < 1500) { // 控制最大尺寸layoutParams.width = (int) (layoutParams.width * 1.05);layoutParams.height = (int) (layoutParams.height * 1.05);}} else { // 缩小图片if (layoutParams.width > 10) { // 控制最小尺寸layoutParams.width = (int) (layoutParams.width / 1.05);layoutParams.height = (int) (layoutParams.height / 1.05);}}// 第一个触点坐标进行迭代x1 = nextX1;y1 = nextY1;// 第二个触点坐标进行迭代x2 = nextX2;y2 = nextY2;// 重新计算两个触点之间的距离distance = (float) Math.sqrt((x1 - x2) * (x1 - x2) + (y1 - y2) * (y1 - y2));}// 重新设置米老鼠图像控件的布局参数ivMickey.setLayoutParams(layoutParams);return true;}});}
}

6、运行程序,查看结果

  • 既可以移动米老鼠,也可以缩放米老鼠

  • 完成!

4.2 安卓触摸事件相关推荐

  1. 安卓学习笔记13:安卓触摸事件

    文章目录 零.学习目标 一.安卓触摸事件概述 1.触摸分类 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 二.安卓单点触摸 三.教学案例--通过单点触摸移动米老鼠 (一)运行效果 ( ...

  2. Android Studio笔记4.2 安卓触摸事件

    文章目录 一.前言 二.笔记4.2 安卓触摸事件 (一)安卓触摸事件概述 1.触摸分类 (1).单点触摸 (2).多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸 ...

  3. 3.2 安卓触摸事件

    文章目录 一.安卓触摸事件概述 1.触摸分类 (1)单点触摸 (2)多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸事件处理机制 二.案例演示:通过单点触摸移动米 ...

  4. 安卓讲课笔记4.2 安卓触摸事件

    文章目录 零.学习目标 一.导入新课 二.新课讲解 (一)安卓触摸事件概述 1.触摸分类 (1)单点触摸 (2)多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸事 ...

  5. Android基础学习笔记13:安卓触摸事件触摸按键

    学习目标 了解安卓触摸动作 熟悉触摸监听器与方法 掌握单点触摸与多点触摸 在Android系统中,触摸是用户最常用,最基础的交互方式,只有弄通触摸事件在系统中的传递处理机制才能更好地增强用户的交互体验 ...

  6. Android Studio 笔记4.2 安卓触摸事件

    文章目录 一.前言 二.笔记4.2 安卓触摸事件 (一)安卓触摸事件概述 1.触摸分类 (1).单点触摸 (2).多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸 ...

  7. Android Studio学习:安卓触摸事件

    (一)安卓触摸事件概述 1.触摸分类 (1)单点触摸 单点触控,只能识别和支持每次一个手指的触控.点击,若同时有两个以上的点被触碰,就不能做出正确反应.很多医院.图书馆等的大厅都有这种触控技术的电脑, ...

  8. 4.3 安卓触摸事件

    文章目录 一.安卓触摸事件概述 1.触摸分类 (1)单点触摸 (2)多点触摸 2.触摸动作 3.触摸监听器 4.触摸方法 5.触点个数与坐标 6.安卓触摸事件处理机制 二.案例演示:通过单点触摸移动米 ...

  9. UE4 安卓触摸事件相关问题

    UE4在安卓端获取输入信息时候,似乎会把触摸事件和PC端的鼠标事件弄混在一起,导致出现一些奇怪的问题. 1. /* 安卓端会把触摸事件读取成PC端的鼠标事件,因为Turn和LookUp在PC端开发时候 ...

最新文章

  1. 生态伙伴 | Worktile入驻飞书,助力企业轻松实现敏捷开发与协作
  2. 每日一博 - Spring Boot Application as a Service
  3. View Components as Tag Helpers,离在线模板编辑又进一步
  4. C/C++高级算法之绘制曼德布洛特集
  5. python教程--__init_.py的作用
  6. web加减乘除法c#_C#的加减乘除的问题
  7. 【AtCoder】AGC009
  8. 装饰器模式在 Collections 类中的应用
  9. 真实VS虚拟,虚拟现实如何定义
  10. MySQL报错: Access denied for user 'root'@'localhost'
  11. BA无标度网络的仿真实现
  12. Java例15.13——使用MVC结构计算三角形面积
  13. 更改浏览器语言(firefox, chrome)详细步骤
  14. 终于有人把“教育内卷”讲明白了
  15. 再谈王垠/王垠—写给清华大学的退学申请
  16. 帕卡贝尔的D大调卡农之由来
  17. HTML 的js中手机号,身份证号等正则表达式表示
  18. 汇编综合实验--学生管理系统
  19. 信息安全——ELGamal数字签名方案的实现
  20. 福瑞股份涉足大数据医疗

热门文章

  1. JAVA子类继承多个_Java的一个子类可以继承自多个父类。
  2. U-Net:大脑MRI海马体语义分割
  3. 如果汉朝有RPA,那么李陵就能枭首10万匈奴,大汉版图扩至地中海
  4. 老年人Theta-Gamma跨频率耦合与工作记忆表现的纵向关系研究
  5. c++实现长方体的面积和体积计算
  6. 银行数字化转型导师坚鹏:学习贯彻二十大精神 解码乡村振兴之道
  7. qq音乐常用接口整理——亲测可用
  8. java-文件上传案例
  9. 分享一个电子发票信息提取工具(Python)
  10. a9 linux 程序下载,金山发布WPS for Linux A9下载