安卓触摸事件的传递

setOnTouchListener()返回值的副作用(触摸事件是否继续往下或往后传递)如下:

返回值效果是否往下层view传递是否往当前view的后续监听传递
true该pointer离开屏幕前的后续所有触摸事件都会传递给该TouchListener
false该pointer离开屏幕前的后续所有触摸事件都不会再传递给该TouchListener

注:

  1. 如果view设置了setOnClickListenersetOnLongClickListener,效果等同于在setOnTouchListener()执行完setOnClickListenersetOnLongClickListener的业务逻辑后返回true
  2. 并非所有view都允许触摸事件往下传递,如Button及其子类就不允许触摸事件向下传递,应该是默认实现了setOnClickListener
  3. 触摸事件执行先后顺序为setOnTouchListener -> setOnLongClickListener -> setOnClickListener

触摸事件的传递可以用以下代码理解:

package com.example.study.controller;import java.lang.reflect.Field;
import java.text.SimpleDateFormat;
import java.util.*;/*** 安卓处理触摸事件示意(为方便理解,假设只有一个手指pointer触摸屏幕)*/
public class TouchEventProcess {// 长按的时间private static final long LONG_CLICK_TIME_MILLIS = 500L;private static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");private boolean touch = false;private boolean longClick = false;private Timer timer;private ViewListener viewListener;private List<View> list = new ArrayList<>();/*** 在这里设置触摸监听*/public TouchEventProcess() {viewListener = new ViewListener();viewListener.setOnTouchListener((view, event) -> {System.out.println(DATE_FORMAT.format(new Date()) + " process touch event:" + MotionEvent.getEventName(event.actionMasked));return false;});viewListener.setOnLongClickListener(view -> {System.out.println(DATE_FORMAT.format(new Date()) + " process long click event");return false;});viewListener.setOnClickListener(view -> {System.out.println(DATE_FORMAT.format(new Date()) + " process click event");});}/*** 多个view** @param event*/public void processTouchEvent(MotionEvent event) {for (View view : list) {if (processTouchEventInView(view, event)) {return;}System.out.println("=====touc event trans to next view=====");}}public boolean processTouchEventInView(View view, MotionEvent event) {// 如果当前view最终返回的是false,不再响应当前pointer的触摸事件if (!viewListener.hasAnyListener()) {reset(event, "no process");return false;}if (viewListener.getOnTouchListener() != null) {touch = viewListener.getOnTouchListener().onTouch(view, event);}if (touch) {reset(event, "process touch");return true;}if (viewListener.getOnLongClickListener() != null) {if (event.actionMasked == MotionEvent.ACTION_DOWN) {timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {longClick = viewListener.getOnLongClickListener().onLongClick(view);timer.cancel();}}, LONG_CLICK_TIME_MILLIS);}}if (longClick) {reset(event, "process long click");return viewListener.hasClickListener();}if (viewListener.getOnClickListener() != null) {if (event.actionMasked == MotionEvent.ACTION_UP) {viewListener.getOnClickListener().onClick(view);}}reset(event, "process end");return viewListener.hasClickListener();}private void reset(MotionEvent event, String msg) {// 抬起手指pointer时重置if (event.actionMasked != MotionEvent.ACTION_UP) {return;}touch = false;longClick = false;if (timer != null) {timer.cancel();}System.out.println(DATE_FORMAT.format(new Date()) + " reset by " + msg);}public interface OnTouchListener extends Listener {boolean onTouch(View view, MotionEvent event);}public interface OnLongClickListener extends Listener {boolean onLongClick(View view);}public interface OnClickListener extends Listener {void onClick(View view);}public interface Listener {}static class ViewListener {private OnTouchListener onTouchListener;private OnLongClickListener onLongClickListener;private OnClickListener onClickListener;public OnTouchListener getOnTouchListener() {return onTouchListener;}public void setOnTouchListener(OnTouchListener onTouchListener) {this.onTouchListener = onTouchListener;}public OnLongClickListener getOnLongClickListener() {return onLongClickListener;}public void setOnLongClickListener(OnLongClickListener onLongClickListener) {this.onLongClickListener = onLongClickListener;}public OnClickListener getOnClickListener() {return onClickListener;}public void setOnClickListener(OnClickListener onClickListener) {this.onClickListener = onClickListener;}public boolean hasAnyListener() {return onTouchListener != null || onLongClickListener != null || onClickListener != null;}public boolean hasClickListener() {return onLongClickListener != null || onClickListener != null;}}static class View {}static class MotionEvent {public static int ACTION_DOWN = 0;public static int ACTION_MOVE = 1;public static int ACTION_UP = 2;int actionMasked;public MotionEvent(int actionMasked) {this.actionMasked = actionMasked;}public static String getEventName(int actionMasked) {for (Field field : MotionEvent.class.getFields()) {try {if ((int) field.get(MotionEvent.class) == actionMasked) {return field.getName();}} catch (IllegalAccessException e) {throw new RuntimeException(e);}}return "unknow";}}public static void main(String[] args) {TouchEventProcess touchEventProcess = new TouchEventProcess();touchEventProcess.list.add(new View());touchEventProcess.list.add(new View());touchEventProcess.list.add(new View());touchEventProcess.processTouchEvent(new MotionEvent(MotionEvent.ACTION_DOWN));touchEventProcess.processTouchEvent(new MotionEvent(MotionEvent.ACTION_MOVE));long click = 100L;long longClick = 1000L;Timer timer = new Timer();timer.schedule(new TimerTask() {@Overridepublic void run() {touchEventProcess.processTouchEvent(new MotionEvent(MotionEvent.ACTION_UP));timer.cancel();}}, longClick); // 调整delay即可切换短按长按}
}

验证代码

可用以下代码验证触摸事件的传递:

布局文件touch_event_test.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"android:id="@+id/touch_test_0"android:layout_width="match_parent"android:layout_height="match_parent"android:background="#F0F0F0"android:orientation="vertical"><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/white"android:padding="5dp"android:text="return true"android:textSize="32sp"android:textStyle="bold" /><!--第一层--><LinearLayoutandroid:id="@+id/touch_test_1_3"android:layout_width="300dp"android:layout_height="300dp"android:background="#7A7374"><!--第二层--><LinearLayoutandroid:id="@+id/touch_test_1_2"android:layout_width="200dp"android:layout_height="200dp"android:background="#1BA784"><!--第三层--><TextViewandroid:id="@+id/touch_test_1_1"android:layout_width="100dp"android:layout_height="100dp"android:background="#EB507E"android:gravity="bottom|right"android:padding="5dp"android:text="1_1"android:textSize="16sp"android:textStyle="bold" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="bottom|right"android:gravity="bottom|right"android:padding="5dp"android:text="1_2"android:textSize="16sp"android:textStyle="bold" /></LinearLayout><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="bottom|right"android:gravity="bottom|right"android:padding="5dp"android:text="1_3"android:textSize="16sp"android:textStyle="bold" /></LinearLayout><!--分割线--><ImageViewandroid:layout_width="match_parent"android:layout_height="1dp"android:layout_marginTop="5dp"android:layout_marginBottom="5dp"android:background="#000000" /><TextViewandroid:layout_width="wrap_content"android:layout_height="wrap_content"android:background="@color/white"android:padding="5dp"android:text="return false"android:textSize="32sp"android:textStyle="bold" /><!--第一层--><LinearLayoutandroid:id="@+id/touch_test_2_3"android:layout_width="300dp"android:layout_height="300dp"android:background="#7A7374"><!--第二层--><LinearLayoutandroid:id="@+id/touch_test_2_2"android:layout_width="200dp"android:layout_height="200dp"android:background="#1BA784"><!--第三层--><TextViewandroid:id="@+id/touch_test_2_1"android:layout_width="100dp"android:layout_height="100dp"android:background="#EB507E"android:gravity="bottom|right"android:padding="5dp"android:text="2_1"android:textSize="16sp"android:textStyle="bold" /><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="bottom|right"android:gravity="bottom|right"android:padding="5dp"android:text="2_2"android:textSize="16sp"android:textStyle="bold" /></LinearLayout><TextViewandroid:layout_width="100dp"android:layout_height="100dp"android:layout_gravity="bottom|right"android:gravity="bottom|right"android:padding="5dp"android:text="2_3"android:textSize="16sp"android:textStyle="bold" /></LinearLayout>
</LinearLayout>

TouchEventTestActivity.java

package org.tao.hetools.activities;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.Toast;import androidx.activity.ComponentActivity;
import androidx.annotation.Nullable;import org.tao.hetools.R;public class TouchEventTestActivity extends ComponentActivity {private static final String TAG = "TouchEventTestActivity";@Overrideprotected void onCreate(@Nullable Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.touch_event_test);initView();}@SuppressLint("ClickableViewAccessibility")private void initView() {View _0 = findViewById(R.id.touch_test_0);View _1_1 = findViewById(R.id.touch_test_1_1);View _1_2 = findViewById(R.id.touch_test_1_2);View _1_3 = findViewById(R.id.touch_test_1_3);View _2_1 = findViewById(R.id.touch_test_2_1);View _2_2 = findViewById(R.id.touch_test_2_2);View _2_3 = findViewById(R.id.touch_test_2_3);_0.setOnTouchListener((view, event) -> {showToast(event, "_0");return true;});// return true_1_1.setOnTouchListener((view, event) -> {showToast(event, "_1_1");return true;});// 设置click longClick事件会对触摸事件在view之间的传递有影响,下同// _1_1.setOnClickListener(view -> Toast.makeText(this, "_1_1 clicked", Toast.LENGTH_SHORT).show());// _1_1.setOnLongClickListener(view -> {//     Toast.makeText(this, "_1_1 long clicked", Toast.LENGTH_SHORT).show();//     return true;// });_1_2.setOnTouchListener((view, event) -> {showToast(event, "_1_2");return true;});_1_3.setOnTouchListener((view, event) -> {showToast(event, "_1_3");return true;});// return false_2_1.setOnTouchListener((view, event) -> {showToast(event, "_2_1");return false;});// _2_1.setOnClickListener(view -> Toast.makeText(this, "_2_1 clicked", Toast.LENGTH_SHORT).show());// _2_1.setOnLongClickListener(view -> {//     Toast.makeText(this, "_2_1 long clicked", Toast.LENGTH_SHORT).show();//     return true;// });_2_2.setOnTouchListener((view, event) -> {showToast(event, "_2_2");return false;});_2_3.setOnTouchListener((view, event) -> {showToast(event, "_2_3");return false;});}private void showToast(MotionEvent event, String msg) {Log.i(TAG, msg + " " + event.getActionMasked());switch (event.getActionMasked()) {case MotionEvent.ACTION_DOWN -> Toast.makeText(this, msg + " press down", Toast.LENGTH_SHORT).show();case MotionEvent.ACTION_UP -> Toast.makeText(this, msg + " press up", Toast.LENGTH_SHORT).show();}}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/498281.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【pytorch】conda安装pytorch

Step 1 打开官网&#xff1a; https://pytorch.org/get-started/locally/ 进行选择对应版本&#xff1a; 复制图中命令执行。 Step 2 验证是否安装成功。 执行&#xff1a; import torch print(torch.cuda.is_available()) print(torch.cuda.device_count()) print(torch.…

项目开发实践——基于SpringBoot+Vue3实现的在线考试系统(四)

文章目录 一、管理员角色功能实现1、添加教师功能实现1.1 页面设计1.2 前端功能实现1.3 后端功能实现1.4 效果展示2、教师管理功能实现2.1 页面设计2.2 前端功能实现2.3 后端功能实现2.3.1 后端查询接口实现2.3.2 后端编辑接口实现2.3.3 后端删除接口实现2.4 效果展示二、代码下…

基于16QAM的载波同步和定时同步性能仿真,采用四倍采样,包括Costas环和gardner环

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 载波同步是…

新服务器ubuntu系统相关操作

1、查看驱动:驱动版本535.216.01能够支持cuda12.2,下面直接使用默认安装的cuda。 2、赋予用户管理员权限。 首先有超级用户(root)权限来编辑 /etc/sudoers 文件,visudo 是一个命令,用于安全地编辑 /etc/sudoers 文件。运行: sudo visudo 在 visudo 编辑器中,找到类似…

2、Bert论文笔记

Bert论文 1、解决的问题2、预训练微调2.1预训练微调概念2.2深度双向2.3基于特征和微调&#xff08;预训练下游策略&#xff09; 3、模型架构4、输入/输出1.输入&#xff1a;2.输出&#xff1a;3.Learned Embeddings(学习嵌入)1. **Token Embedding**2. **Position Embedding**3…

python 渗透开发工具之SQLMapApi Server不同IP服务启动方式处理 解决方案SqlMapApiServer外网不能访问的情况

目录 说在前面 什么是 SQLMapAPI 说明 sqlmapApi能干什么 sqlmapApi 服务安装相关 kali-sqlmap存放位置 正常启动sqlmap-api server SqlMapApi-Server 解决外网不能访问情况 说在前面 什么是sqlmap 这个在前面已经说过了&#xff0c;如果这个不知道&#xff0c;就可以…

操作系统论文导读(八):Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个

Schedulability analysis of sporadic tasks with multiple criticality specifications——具有多个关键性规范的零星任务的可调度性分析 目录 一、论文核心思想 二、基本定义 2.1 关键性指标 2.2 任务及相关参数定义 2.3 几个基础定义 三、可调度性分析 3.1 调度算法分…

技术速递|调用异步功能 - WinForms 在 .NET 9 中的未来发展

作者&#xff1a; Klaus Loeffelmann 排版&#xff1a;Alan Wang 随着 .NET 的不断发展&#xff0c;WinForms 开发者可用的工具也在不断进步&#xff0c;这使得开发更加高效且应用响应更迅速。在 .NET 9 中&#xff0c;我们很高兴引入了一系列新的异步 API&#xff0c;这些 API…

Docker-构建自己的Web-Linux系统-镜像webtop:ubuntu-kde

介绍 安装自己的linux-server,可以作为学习使用&#xff0c;web方式访问&#xff0c;基于ubuntu构建开源项目 https://github.com/linuxserver/docker-webtop安装 docker run -d -p 1336:3000 -e PASSWORD123456 --name webtop lscr.io/linuxserver/webtop:ubuntu-kde登录 …

【每日学点鸿蒙知识】箭头函数、Watch状态变量、H5获取定位数据、前后台切换、长按事件

【每日学点鸿蒙知识】箭头函数、Watch状态变量、H5获取定位数据、前后台切换、长按事件 1、HarmonyOS confirm: () > void () > { }&#xff1f; confirm: () > void () > { }是什么格式。 是一个箭头函数&#xff0c;它的类型是 () > void&#xff0c;表示…

【人工智能机器学习基础篇】——深入详解监督学习之模型评估:掌握评估指标(准确率、精确率、召回率、F1分数等)和交叉验证技术

深入详解监督学习之模型评估 在监督学习中&#xff0c;模型评估是衡量模型性能的关键步骤。有效的模型评估不仅能帮助我们理解模型在训练数据上的表现&#xff0c;更重要的是评估其在未见数据上的泛化能力。本文将深入探讨监督学习中的模型评估方法&#xff0c;重点介绍评估指…

如何使用React,透传各类组件能力/属性?

在23年的时候&#xff0c;我主要使用的框架还是Vue&#xff0c;当时写了一篇“如何二次封装一个Vue3组件库&#xff1f;”的文章&#xff0c;里面涉及了一些如何使用Vue透传组件能力的方法。在我24年接触React之后&#xff0c;我发现这种扩展组件能力的方式有一个专门的术语&am…

点进CSS选择器

CSS 1.直接在标签的style属性进行设置(行内式) //写在数据单元格td标签内的stytle&#xff0c;设置color颜色和font-size字体大小&#xff1b; <td rowspan"3" style"color: red;font-size: 12px;">Web技术与应用</td> 2.写在head标签中的…

Python基于卷积神经网络的车牌识别系统开发与实现

1. 简介 车牌识别是人工智能在交通领域的重要应用&#xff0c;广泛用于高速违章检测、停车场管理和智能交通系统等场景。本系统通过基于卷积神经网络&#xff08;CNN&#xff09;的深度学习算法&#xff0c;结合 Python 和 MySQL 实现车牌的快速识别与管理。 系统特点&#x…

【PDF物流单据提取明细】批量PDF提取多个区域内容导出表格或用区域内容对文件改名,批量提取PDF物流单据单号及明细导出表格并改名的技术难点及小节

相关阅读及下载&#xff1a; PDF电子物流单据&#xff1a; 批量PDF提取多个区域局部内容重命名PDF或者将PDF多个局部内容导出表格&#xff0c;具体使用步骤教程和实际应用场景的说明演示https://mp.weixin.qq.com/s/uCvqHAzKglfr40YPO_SyNg?token720634989&langzh_CN扫描…

运行python程序报错 undefined symbol: ffi_type_uint32 的参考解决方法

文章目录 写在前面一、问题描述二、解决方法参考链接 写在前面 自己的测试环境&#xff1a; Ubuntu20.04 ROS-Noetic 一、问题描述 运行 python 程序出现如下问题&#xff1a; Traceback (most recent call last):File "<string>", line 1, in <module&…

鱼眼相机模型与去畸变实现

1.坐标系说明 鱼眼相机模型涉及到世界坐标系、相机坐标系、图像坐标系、像素坐标系之间的转换关系。对于分析鱼眼相机模型&#xff0c;假定世界坐标系下的坐标点,经过外参矩阵的变换转到相机坐标系&#xff0c;相机坐标再经过内参转换到像素坐标&#xff0c;具体如下 进一步进…

ASP.NET Core Web API Hangfire

ASP.NET Core Web API Hangfire 前言一、安装二、相关代码1.代码片段2.代码片段3.运行效果 三、测试代码1.即发即弃作业2.延迟作业3.重复作业4.延续作业5.页面调度作业 前言 &#x1f468;‍&#x1f4bb;&#x1f468;‍&#x1f33e;&#x1f4dd;记录学习成果&#xff0c;以…

DevOps实战:用Kubernetes和Argo打造自动化CI/CD流程(1)

DevOps实战&#xff1a;用Kubernetes和Argo打造自动化CI/CD流程&#xff08;1&#xff09; 架构 架构图 本设计方案的目标是在一台阿里云ECS服务器上搭建一个轻量级的Kubernetes服务k3s节点&#xff0c;并基于Argo搭建一套完整的DevOps CI/CD服务平台&#xff0c;包括Argo CD…

【openGauss】正则表达式次数符号“{}“在ORACLE和openGauss中的差异

一、前言 正则作为一种常用的字符串处理方式&#xff0c;在各种开发语言&#xff0c;甚至数据库中&#xff0c;都有自带的正则函数。但是正则函数有很多标准&#xff0c;不同标准对正则表达式的解析方式不一样&#xff0c;本次在迁移一个ORACLE数据库到openGauss时发现了一个关…