浅谈 Android焦点管理机制 事件分发机制

什么是焦点

  • 焦点能够让 视图和窗口 可以接受和处理 按键事件和导航事件
  • 在 Android 中,按键事件和导航事件通常指的是 与物理按键和输入设备(如键盘、遥控器、游戏手柄等)相关的交互事件
    焦点的处理对于非触摸屏设备(如电视盒子、某些游戏设备等)非常重要。

有哪些些常见的按键事件和导航事件

按键事件 (Key Events)

KeyEvent.KEYCODE_BACK: 返回键。用于导航回上一个屏幕或关闭弹出的菜单或对话框。

KeyEvent.KEYCODE_MENU: 菜单键。通常用于打开一个上下文菜单或应用的主菜单。

KeyEvent.KEYCODE_HOME: 主页键。通常用于返回设备的主屏幕。

KeyEvent.KEYCODE_VOLUME_UP & KeyEvent.KEYCODE_VOLUME_DOWN: 音量增加和减少键。用于控制设备的音量。

KeyEvent.KEYCODE_DPAD_UP, KEYCODE_DPAD_DOWN, KEYCODE_DPAD_LEFT, KEYCODE_DPAD_RIGHT: 方向键。用于在界面中导航,特别是在非触摸屏设备上。

KeyEvent.KEYCODE_DPAD_CENTER or KeyEvent.KEYCODE_ENTER: 确认键。用于选择当前聚焦的项目。

KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE, KEYCODE_MEDIA_NEXT, KEYCODE_MEDIA_PREVIOUS: 媒体控制键。用于控制媒体播放。

导航事件 (Navigation Events)

轨迹球导航 (Trackball Navigation): 一些设备配备了轨迹球,用于在界面上导航。

键盘导航 (Keyboard Navigation): 使用键盘的方向键进行界面导航。

游戏手柄导航 (Gamepad Navigation): 使用游戏手柄上的摇杆或方向键进行界面导航。

处理按键事件

在 Android 应用中处理按键事件通常涉及重写 Activity 或 View 的 onKeyDown 和 onKeyUp 方法。例如:

@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
// 处理返回键的操作
return true;
}
return super.onKeyDown(keyCode, event);
}

焦点的分类

焦点可以分为两种:窗口焦点和视图焦点

  • 窗口焦点(Window Focus):通常指的是一个 Activity、Dialog 或者 PopupWindow 等窗口是否能接收键盘输入和其他导航事件

一个窗口只有在获得焦点时,才能接收到按键事件(如返回键、菜单键等)。

  • 视图焦点(View Focus):指的是用户界面中的某个特定视图(如 EditText、Button 等) 是否能接收键盘输入。

为什么视图需要申请焦点?

一个目的 :确保视图能够 正常 接收和处理 用户的输入

三个目标:

  1. 输入事件处理:只有拥有焦点的视图才能接收键盘输入事件,这些事件包括文字输入、按键事件(如返回键、菜单键等)。
  2. 物理按键和输入设备的响应:对于那些可以响应物理按键(如游戏手柄、遥控器、硬件键盘等)的设备来说,焦点控制对于视图来接收和处理这些按键事件至关重要。
  3. 导航和可访问性:焦点状态也用于辅助功能,如屏幕阅读器,帮助视障用户导航应用界面。同时,使用方向键(如 D-pad 或键盘上的箭头键)在不同控件间导航时,系统也是根据哪个控件拥有焦点来确定下一个获得焦点的控件。

在代码中,可以调用视图的 requestFocus() 方法来申请焦点。例如,如果你想要一个 Button 在 Activity 启动时就获取焦点,你可以:

如何申请焦点?

调用requestFocus方法

Button button = findViewById(R.id.my_button);
button.requestFocus();

也可以在 XML 布局文件中使用属性来指定某个视图应当获得焦点:

<Button
android:id="@+id/my_button"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Press Me"
android:focusable="true"
android:focusableInTouchMode="true" />

focusable 设置为 true 表示这个 Button 可以获得焦点,focusableInTouchMode 设置为 true 表示这个 Button 在触摸模式下也可以获得焦点。

申请焦点带来的异常情况

当一个应用程序或视图请求焦点时,可能会触发系统行为,如显示或隐藏导航栏(也被称作 dock 栏)。

开发中经常会碰到这种需求:弹框弹出的时候不让dock栏一同弹出,当申请焦点 dock栏自动弹出分为下面几种情况:

  • 键盘显示:在某些情况下,当一个输入框(EditText)获得焦点时,系统会自动显示软键盘。随着软键盘的弹出,导航栏也会一并显示,因为用户可能需要用到导航键(比如返回键)来关闭软键盘。
  • 全屏模式下焦点变更:如果应用处于全屏模式,当申请焦点时,系统可能会认为用户需要进行某种交互,因此会系统会自动退出全屏模式并显示导航栏供用户使用。
  • 焦点改变监听:如果某些视图上设置了焦点改变监听器(OnFocusChangeListener),在这些监听器中,可能有代码触发了导航栏的显示。
  • 系统窗口标志更改:申请焦点可能导致窗口的某些 UI 标志被重置,特别是那些控制系统 UI 可见性的标志

如何解决

  • 维持窗口的全屏Flag:如果问题是在全屏模式下发生的,在申请焦点之后需要去 重新设置全屏模式相关的窗口标志。
  • 调整焦点策略不需要时不要申请焦点
  • 监听焦点变化重新设置可见性:设置焦点变化监听器,当焦点变化时,重新应用 UI 标志,以保持 dock 栏的隐藏状态

代码如下:

View decorView = getWindow().getDecorView();
decorView.setOnFocusChangeListener(new View.OnFocusChangeListener() {
@Override
public void onFocusChange(View v, boolean hasFocus) {
if (hasFocus) {
// Set the system UI visibility flags
decorView.setSystemUiVisibility(
View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY);
}
}
});

什么是触摸事件?

触摸事件(Touch Events)是 用户与屏幕 的交互,比如点击(tap)、长按(long press)、滑动(swipe)等。

触摸事件涉及到事件分发,相关规则可以查看Andorid开发艺术探索

焦点与触摸事件的关系

  • 焦点不是触摸事件的必要条件:一个视图不需要有焦点就能接收到触摸事件

比如,在一个 ScrollView 中滑动屏幕,视图可以处理滑动事件,即使它没有焦点。

  • 可聚焦视图可以响应按键事件:一个视图如果可以获得焦点(isFocusable 为 true),则它可以响应如按键事件(key events)。

例如,当一个 Button 获得焦点后,用户可以通过按下硬件键盘的 Enter 键来触发点击事件。

  • 焦点转移:用户触摸屏幕上的一个可聚焦的视图时,该视图可能获取焦点(如果它的 isFocusableInTouchMode 设置为 true)。

  • 焦点决定键盘输入:例如,当一个 EditText 获得焦点后,它可以接收键盘输入

  • 触摸事件可以改变焦点状态

例如,当用户在一个 ListView 中触摸一个条目时,该条目可能获得焦点。

不同情况下 焦点 的触摸事件的 处理

  1. PopupWindow 或 Dialog 等窗口:
  • 如果窗口是可以聚焦的 则 可以响应按键事件,其内部的视图也可以响应触摸事件。

  • 如果窗口不可以聚焦 ,触摸事件仍然可以被内部视图捕获,但按键事件将可能被后面的窗口处理。

  1. 具体的某个视图:
  • 设置不可聚焦不获取焦点的视图:如果触摸了一个 isFocusable 设置为 false 的视图,它将不会获得焦点,但它仍然可以处理触摸事件。

  • 已经获取了焦点,该视图可以直接处理触摸事件,焦点状态不会改变。

  • 当前没有焦点但是设置了可聚焦的状态,该视图可能会获得焦点,并处理触摸事件。

总结一下:
一个没有焦点的视图可以接收触摸事件,但无法接收键盘等导航事件。
反之,一个有焦点的视图可以响应键盘事件,并且如果它是可触摸的,也可以响应触摸事件。

焦点只是决定你是否能够响应物理按键和键盘和无障碍服务,且任何一个时间只能有一个视图持有焦点,而触摸事件 可以决定让哪个视图拥有焦点(通过可聚焦状态和触摸事件的位置)

多窗口情况下 的 焦点管理和事件分发

事件分发和视图是否持有焦点无关,在多窗口环境中,触摸事件首先被最上层的窗口捕获,如果这个窗口不消费(consume)该事件,事件可以继续向下传递至下一个窗口。

在多窗口环境中,焦点是用来确定哪个视图或窗口将接收键盘输入或导航事件。如果新弹出的窗口没有申请焦点,那么焦点还在原窗口上;否则就会进行流转。

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

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

相关文章

【LeetCode每日一题】2645. 构造有效字符串的最少插入数(计算组数+动态规划+考虑相邻字母)

2024-1-11 文章目录 [2645. 构造有效字符串的最少插入数](https://leetcode.cn/problems/minimum-additions-to-make-valid-string/)方法一&#xff1a;计算组数方法二&#xff1a;动态规划方法三: 考虑相邻字母 2645. 构造有效字符串的最少插入数 方法一&#xff1a;计算组数 …

uniapp中实现H5录音和上传、实时语音识别(兼容App小程序)和波形可视化

文章目录 Recorder-UniCore插件特性集成到项目中调用录音上传录音ASR语音识别 在uniapp中使用Recorder-UniCore插件可以实现跨平台录音功能&#xff0c;uniapp自带的recorderManager接口不支持H5、录音格式和实时回调onFrameRecorded兼容性不好&#xff0c;用Recorder插件可避免…

Leetcode 416 分割等和子集

题意理解&#xff1a; 给你一个 只包含正整数 的 非空 数组 nums 。请你判断是否可以将这个数组分割成两个子集&#xff0c;使得两个子集的元素和相等。 即将数组的元素分成两组&#xff0c;每组数值sum(nums)/2 若能分成这样的两组&#xff0c;则返回true,否则返回false 本质上…

RobotStudio机器人码垛课程设计

一、任务需求 1、创建动态夹具&#xff08;600*400*50&#xff09; 2、创建物料&#xff08;600*400*200&#xff09; 3、起码按顺序码垛放置 4 个不同位置 二、软件常用操作及其快捷键 &#xff08;推荐自己按这些步骤操作一下&#xff0c;能明白这些操作的具体意义&#…

Java版直播商城:电商源码、小程序、三级分销及 免 费 搭 建 方案

一、技术选型 java开发语言&#xff1a;java是一种跨平台的编程语言&#xff0c;适用于大型企业级应用开发。使用java开发直播商城可以保证系统的稳定性和可扩展性。 spring boot框架&#xff1a;spring boot是一个快速构建spring应用的框架&#xff0c;简化了开发过程&#xf…

c# 动态更新配置文件

在.Net Framework版本可以使用ConfigurationManager 通常是指app.config或web.config 命名空间 System.Configuration下的ConfigurationManagerprivate void UpdateConfig(string key,string value) {Configuration config ConfigurationManager.OpenExeConfiguration(Config…

[渗透测试学习] Clicker - HackTheBox

文章目录 信息搜集代码审计反弹shell提权 信息搜集 nmap扫描一下端口 nmap -sV -sC -v -p- --min-rate 1000 10.10.11.232扫描结果 22/tcp open ssh 80/tcp open http Apache httpd 2.4.52 ((Ubuntu)) //重定向 111/tcp open rpcbind 2-4 (RPC #100000)我们往…

如何查看Ubuntu内存的使用情况

在Linux系统中&#xff0c;了解内存使用情况对于系统管理和性能优化非常重要。以下是一些常用的命令&#xff0c;以及它们的详细使用说明&#xff1a; 1. free 命令 用途: free 命令用于显示系统中空闲和已用的物理内存及交换内存。示例: 输入命令: free -m输出解释: 这将以M…

python 爬虫 request get或post传参

爬虫传参 import requestsurl http://www.xxx# get 或 post 传参数据 data {"pageNo": 1652,"pageSize": 10, }headers {Cookie: ,Host: ,Origin: ,Referer: ,User-Agent: , }# get 请求 # res requests.get( # url, # paramsdata, # hea…

重磅消息:2024北京国际智能科技展览会(世亚智博会)官宣定档

在数字新时代的浪潮下&#xff0c;智能科技作为推动社会进步的重要力量&#xff0c;正在以前所未有的速度改变着我们的生活和工作方式。为了进一步推动智能科技的发展和交流&#xff0c;2024北京国际智能科技展览会&#xff08;简称世亚智博会&#xff09;将于2024年6月份在北京…

[C#]winform使用纯opencvsharp部署yolox-onnx模型

【官方框架地址】 https://github.com/Megvii-BaseDetection/YOLOX 【算法介绍】 YOLOX是一个高性能的目标检测算法&#xff0c;它是基于YOLO&#xff08;You Only Look Once&#xff09;系列算法的Anchor Free版本。YOLOX由Megvii Technology的研究团队开发&#xff0c;并在…

linux—多服务免密登录

文档结构 概念简介配置操作 概念简介 配置操作 场景&#xff1a;在部署gp集群时&#xff0c;希望 master 节点可以使用gpadmin用户可以实现免密登录 slave1和 slave2 节点&#xff1b; step_1: IP映射 xx.xx.xx.101 server-slave1 xx.xx.xx.102 server-slave2说明&#x…

使用Spring Boot集成中间件:基础篇

使用Spring Boot集成中间件&#xff1a;Redis基础讲解 在现代应用开发中&#xff0c;中间件在构建高效、可扩展的系统方面起着至关重要的作用。而Spring Boot作为一种快速开发框架&#xff0c;提供了丰富的集成中间件的能力&#xff0c;使得我们能够轻松地将各种中间件引入到我…

在 Windows IIS 生成证书签名请求(CSR)

本操作方法将逐步指导您生成证书签名请求&#xff08;CSR&#xff09;。 这些过程已在Windows 10的IIS 10上进行了测试&#xff0c;但也将在IIS 7.x和8.x中运行。 启动IIS管理器。 Start 开始 IIS管理器。 另外一种快速的方法是打开 运行 命令&#xff0c;然后键入 inetmgr 并…

深度学习算法应用实战 | 利用 CLIP 模型进行“零样本图像分类”

文章目录 1. 零样本图像分类简介1.1 什么是零样本图像分类?1.2 通俗一点的解释 2. 模型原理图3. 环境配置4. 代码实战5. Gradio前端页面5.1 什么是 Gradio ? 6 进阶操作7. 总结 1. 零样本图像分类简介 1.1 什么是零样本图像分类? “零样本图像分类”&#xff08;Zero-shot …

解决org.apache.jasper.JasperException异常!

解决org.apache.jasper.JasperException异常&#xff01; 大家好&#xff0c;我是免费搭建查券返利机器人赚佣金就用微赚淘客系统3.0的小编&#xff0c;也是冬天不穿秋裤&#xff0c;天冷也要风度的程序猿&#xff01;今天&#xff0c;我们将一同面对在Java Web开发中常见的问题…

C++获取内存使用情况

在程序编程过程中&#xff0c;为了防止出现内存泄漏情况出现&#xff0c;需要持续关注内存程序内存占用情况。如下方式实现获取当前进程内存使用情况&#xff1a; linux&#xff1a; void my_top(string path, bool flag) {if(flag){FILE* read_top fopen("/proc/self/…

debian 12 zabbix 6.0LTS部署

数据库要求 数据库版本不对&#xff0c;zabbix-server启动不起来 MySQL/Percona8.0.XRequired if MySQL (or Percona) is used as Zabbix backend database. InnoDB engine is required. We recommend using the MariaDB Connector/C library for building server/proxy.Maria…

使用GPT大模型调用工具链

本文特指openai使用sdk的方式调用工具链。 安装openai pip install openai export OPENAI_API_KEY"YOUR OPENAI KEY" 定义工具函数 from openai import OpenAI import jsonclient OpenAI() #工具函数 def get_current_weather(location, unit"fahrenheit&q…

使用懒加载 + 零拷贝后,程序的秒开率提升至99.99%

目录 一、5秒钟加载一个页面的真相二、优化四步走1、“懒加载”2、线上显示 就读取一个文件&#xff0c;为什么会慢呢&#xff1f; 三、先从上帝视角&#xff0c;了解一下啥子是IO流四、写个栗子&#xff0c;测试一下1、通过字符输入流FileReader读取2、通过缓冲流BufferedRea…