android press 事件监测

本文深入解析Android触摸事件中的预压、按下和长按三种监测机制,详细阐述了每种事件的触发条件、处理流程及关键代码实现,包括如何通过异步延迟消息和Runnable接口实现事件间的转换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Android的触摸消息中,已经实现了三种监测,它们分别是
 
1)pre-pressed:对应的语义是用户轻触(tap)了屏幕

 


 

 


2)pressed:对应的语义是用户点击(press)了屏幕
 
3)long pressed:对应的语义是用户长按(long press)了屏幕
 
下图是触摸消息随时间变化的时间轴示意图:
 

 

其中,t0和t1定义在ViewConfiguration类中,标识了tap和longpress的超时时间,定义如下:
 
1./**
2. * Defines the duration in milliseconds we will wait to see if a touch event 
3. * is a tap or a scroll. If the user does not move within this interval, it is
4. * considered to be a tap. 
5. */ 
6.private static final int TAP_TIMEOUT = 115; // t0  
7. 
8./** 
9. * Defines the duration in milliseconds before a press turns into
10. * a long press
11. */ 
12.private static final int LONG_PRESS_TIMEOUT = 500; // t1 
代码中实现监测的地方在View类的OnTouchEvent函数中,当View监测到ACTION_DOWN事件时,首先发送一个延迟为t0的异步消息,代码如下:
 1.case MotionEvent.ACTION_DOWN: 
2.    if (mPendingCheckForTap == null) { 
3.        mPendingCheckForTap = new CheckForTap(); 
4.    } 
5.    mPrivateFlags |= PREPRESSED; 
6.    mHasPerformedLongPress = false; 
7.    postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout()); 
8.    break; 
如果在t0时间内用户释放了屏幕,即ACTION_UP事件在t0时间内发生,则本次触摸对应的是pre-pressed处理代码,语义是"用户轻触(TAP)了一下屏幕";如果用户在t1时间内释放了屏幕,那么本次操作是一个"press"操作;如果用户超过t1时间释放屏幕,则系统认为监测到了长按事件。其中处理"press"操作的代码在类CheckForTap类中,处理长按操作的代码在类CheckForLongPress类中。而处理pre-pressed的代码在ACTION_UP事件响应中,ACTION_UP事件响应中大部分代码用于处理触摸的状态变化,如下所示:
 1.case MotionEvent.ACTION_UP: 
2.    boolean prepressed = (mPrivateFlags & PREPRESSED) != 0; //获取prepressed状态  
3.    if ((mPrivateFlags & PRESSED) != 0 || prepressed) { //如果是pressed状态或者是prepressed状态,才进行处理  
4.        // 如果当前view不具有焦点,则需要先获取焦点,因为我们当前处理触摸模式  
5.        boolean focusTaken = false; 
6.        if (isFocusable() && isFocusableInTouchMode() && !isFocused()) { 
7.            focusTaken = requestFocus(); // 请求获得焦点  
8.        } 
9. 
10.        if (!mHasPerformedLongPress) { // 是否处理过长按操作了,如果是,则直接返回  
11.            // 进入该代码段,说明这是一个tap操作,首先移除长按回调操作  
12.            removeLongPressCallback();  
13. 
14.            // Only perform take click actions if we were in the pressed state  
15.            if (!focusTaken) { 
16.                // Use a Runnable and post this rather than calling  
17.                // performClick directly. This lets other visual state  
18.                // of the view update before click actions start.  
19.                if (mPerformClick == null) { 
20.                    mPerformClick = new PerformClick(); 
21.                } 
22.                if (!post(mPerformClick)) { 
23.                    performClick(); // 执行点击的处理函数  
24.                } 
25.            } 
26.        } 
27. 
28.        if (mUnsetPressedState == null) { 
29.            mUnsetPressedState = new UnsetPressedState(); 
30.        } 
31. 
32.        if (prepressed) { 
33.            mPrivateFlags |= PRESSED; 
34.            refreshDrawableState(); 
35.            // 发送重置触摸状态的异步延迟消息  
36.            postDelayed(mUnsetPressedState, 
37.                    ViewConfiguration.getPressedStateDuration()); 
38.        } else if (!post(mUnsetPressedState)) { 
39.            // If the post failed, unpress right now  
40.            mUnsetPressedState.run(); 
41.        } 
42.        removeTapCallback(); // 移除tap的回调操作  
43.    } 
44.    break; 
在上面的代码分析中,可以看出,整个监测过程涉及到两个Runnable对象和一个利用Handler发送异步延迟消息的函数,下面就来分析一下:
 


1)PostDelayed函数
 
该函数的主要工作是获取UI线程的Handler对象,然后调用Handler类的postDelayed函数将指定的Runnable对象放到消息队列中。
 
1.public boolean postDelayed(Runnable action, long delayMillis) { 
2.    Handler handler; 
3.    if (mAttachInfo != null) { 
4.        handler = mAttachInfo.mHandler; 
5.    } else { 
6.        // Assume that post will succeed later  
7.        ViewRoot.getRunQueue().postDelayed(action, delayMillis); 
8.        return true; 
9.    } 
10. 
11.    return handler.postDelayed(action, delayMillis); 
12.} 
2)CheckForTap类
该类实现了Runnable接口,在run函数中设置触摸标识,并刷新Drawable的状态,同时用于发送一个检测长按事件的异步延迟消息,代码如下:
 
1.private final class CheckForTap implements Runnable { 
2.    public void run() { 
3.        // 进入该函数,说明已经过了ViewConfiguration.getTapTimeout()时间,  
4.        // 即pre-pressed状态结束,宣告触摸进入pressed状态  
5.        mPrivateFlags &= ~PREPRESSED;  
6.        mPrivateFlags |= PRESSED; 
7.        refreshDrawableState(); // 刷新控件的背景Drawable  
8.        // 如果长按检测没有被去使能,则发送一个检测长按事件的异步延迟消息  
9.        if ((mViewFlags & LONG_CLICKABLE) == LONG_CLICKABLE) { 
10.            postCheckForLongClick(ViewConfiguration.getTapTimeout()); 
11.        } 
12.    } 
13.} 
14. 
15.private void postCheckForLongClick(int delayOffset) { 
16.    mHasPerformedLongPress = false; 
17. 
18.    // 实例化CheckForLongPress对象  
19.    if (mPendingCheckForLongPress == null) { 
20.        mPendingCheckForLongPress = new CheckForLongPress(); 
21.    } 
22.    mPendingCheckForLongPress.rememberWindowAttachCount(); 
23.    // 调用PostDelayed函数发送长按事件的异步延迟消息  
24.    postDelayed(mPendingCheckForLongPress, 
25.            ViewConfiguration.getLongPressTimeout() - delayOffset); 
26.} 
 
3)CheckForLongPress类
 
该类定义了长按操作发生时的响应处理,同样实现了Runnable接口
 
1.class CheckForLongPress implements Runnable { 
2. 
3.    private int mOriginalWindowAttachCount; 
4. 
5.    public void run() { 
6.        // 进入该函数,说明检测到了长按操作  
7.        if (isPressed() && (mParent != null) 
8.                && mOriginalWindowAttachCount == mWindowAttachCount) { 
9.            if (performLongClick()) {  
10.                mHasPerformedLongPress = true; 
11.            } 
12.        } 
13.    } 
14. 
15.    public void rememberWindowAttachCount() { 
16.        mOriginalWindowAttachCount = mWindowAttachCount; 
17.    } 
18.} 
19. 
20.public boolean performLongClick() { 
21.    sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED); 
22. 
23.    boolean handled = false; 
24.    if (mOnLongClickListener != null) { 
25.        // 回调用户实现的长按操作监听函数(OnLongClickListener)  
26.        handled = mOnLongClickListener.onLongClick(View.this); 
27.    } 
28.    if (!handled) { 
29.        // 如果OnLongClickListener的onLongClick返回false  
30.        // 则需要继续处理该长按事件,这里是显示上下文菜单  
31.        handled = showContextMenu(); 
32.    } 
33.    if (handled) { 
34.        // 长按操作事件被处理了,此时应该给用户触觉上的反馈  
35.        performHapticFeedback(HapticFeedbackConstants.LONG_PRESS); 
36.    } 
37.    return handled; 
38.} 

本篇文章来源于 Linux公社网站(www.linuxidc.com)  原文链接:http://www.linuxidc.com/Linux/2012-08/67979.htm

<think>首先,用户在询问如何将Android中的值"1204282uv"转换为伏特并移除单位。值为"1204282uv","uv"很可能指的是微伏(microvolt),因为微伏的缩写通常是μV或uV,而用户写了"uv",可能是个拼写错误或简写。所以,"1204282uv"意味着1204282微伏。-1微伏(μV)=10^{-6}伏特(V)因此,要将微伏转换为伏特,我需要除以1,000,000。计算:1204282÷1,000,000=1.204282V所以,结果是1.204282伏特(Volts)。用户还提到"removeunit",意思是移除单位。因此,在输出时,我应该只给出数字部分,而不包含"V"或任何单位标识。用户提供了引用内容,但根据系统指令,我需要参考这些引用和用户的历史问题。用户说:"上述引用仅供参考,并不是用户真正的需求,请尽可能多的参考用户上一次的问题和你的回答。"回想用户的问题历史:-在系统级指令中,用户引用了几个内容:[1]关于设备树中的按键配置,press-threshold-microvolt等;[2]音频驱动配置,包括microvolt阈值;[3]关于CPUFreq的讨论,它提到调整电压。当前问题是:"我想将Android中的1204282uv转换为伏特并去除单位请问androidmicrovolttovoltconversionremoveunit1204282uv"用户的问题似乎是独立的:直接转换数字。但引用涉及Android设备树的配置,包括电压相关的设置。用户可能正在处理设备树或驱动程序中与电压相关的值。在引用[2]中,有像"press-threshold-microvolt=<33000>;"这样的行,其中值以微伏为单位。在引用[1]和[2]中,值是以微伏写的,并且在驱动程序中,它们可能被用来检测按键或事件。用户在转换"1204282uv",这可能是类似上下文中的值。用户说"android",所以这可能在Android内核开发或设备树配置中。但核心问题是关于单位转换。回答结构:-系统指令要求回答使用中文。-行内数学表达式用$...$格式,例如计算。-独立公式用$$...$$格式。-回答结构清晰,帮助用户逐步解决问题。-生成相关问题。逐步解决:1.确认输入值:1204282uv。假设"uv"意为微伏(microvolt)。2.解释转换:1μV=10^{-6}V。数学:伏特数=微伏数×10^{-6}或用公式:V=μV/1,000,0003.计算:1204282÷1000000=1.204282在编程中,去除单位后输出数字1.204282。4.由于在Android中,如果这是代码的一部分,可能涉及解析字符串如"1204282uv",提取数字,然后转换。5.从引用[2],在dts文件中,值是以数字给出的,如"33000",单位是隐含的(从属性名如press-threshold-microvolt)。但在用户输入中,有"1204282uv",所以可能用户在字符串形式中有这个值。用户的问题:"androidmicrovolttovoltconversionremoveunit1204282uv",可能意思是如何在Android开发中处理这样的字符串转换。在C代码或DTS中,值直接作为数字给出,没有字符串单位。例如,在引用[2]:"press-threshold-microvolt=<33000>;"–33000isanumberinmicrovolts.所以,用户可能在处理一个带有单位的字符串值。或许"1204282uv"是表示一个带单位的电压值。在我的回答中,我应该专注于转换,并提及在上下文中如何处理的建议。步骤:-解释单位转换。-给出计算。-建议在代码中如何实现。使用数学表达式:-行内:微伏到伏特转换公式:$V=\frac{\muV}{1000000}$-独立公式:如果需要。计算:$1204282\,\muV=\frac{1204282}{1000000}\,V=1.204282\,V$然后移除单位后:1.204282在编程中,如果用户正在写代码来解析这样的字符串:例如,在Java或C中,读取字符串,提取数字部分,转换为整数或浮点数,然后除以1000000.0。由于在Android中,可能是Java或Native代码。引用中提到设备树(dts文件),所以可能是内核模块,C代码。在引用[2]中,有"press-threshold-microvolt=<33000>;",所以值在dts中是整数。用户有"1204282uv",这可能来自日志或其他地方,其中单位被包含。所以,建议解析字符串。回答结构:1.**理解问题**:用户想将1204282微伏转换为伏特,并只保留数字。2.**解释转换**:1微伏(μV)=10^{-6}伏特(V),因此微伏除以1,000,000得到伏特。3.**计算结果**:1204282/1000000=1.2042824.**移除单位**:结果数值是1.2042825.**在Android中的应用**:如果这是字符串值,需要用代码解析数字部分并计算。生成相关问题:最后生成相关问题。引用用户提供的引用:引用末尾添加引用标识如[^1]引用内容中:-[^1]:按键配置,有press-threshold-microvolt。-[^2]:音频驱动配置,键值。-[^3]:CPUFreq当前问题有关单位转换,相关但不是直接相关。所以,在回答中,可以提及在dts文件或驱动程序中处理电压值的上下文。例如,在引用[2]中,值以微伏给出,但驱动程序可能内部处理为伏特或其他单位。但通常,在硬件描述中,微伏是常见的。在我的回答中,参考这些来描述类似场景。最后,生成相关问题。相关问题想法:1.如何在C代码中解析带有单位的电压值?2.设备树中电压属性的描述。3.微伏和伏特在功耗中的应用。4.去除单位后的值在计算中的使用。等等。完整回答在中文。</think> 根据您的查询,您想将值“1204282uv”从微伏(microvolt, μV)转换为伏特(V),并移除单位。这里,“uv”很可能指的是微伏(μV),在工程上下文中常用“u”代替希腊字母“μ”。我会基于您的需求,逐步解释和计算。另外,考虑到您提供的引用内容(尤其是引用[^1]和[^2],它们涉及 Android 设备树中的电压配置,如 `press-threshold-microvolt`),这个值可能与 Android 内核开发相关,例如设备树(DTS)文件中的键值检测或传感器数据。我会先解释单位转换原理,再给出计算和结果,最后提供在 Android 开发中的实用建议。 ### 步骤 1: 理解单位和转换原理 - 微伏(μV)和伏特(V)是电压单位,转换关系为: 1 微伏(μV) = $10^{-6}$ 伏特(V),或等价于: $$ V = \frac{\mu V}{1000000} $$ 这里,$V$ 表示伏特值,$\mu V$ 表示微伏值。 - 您的输入值“1204282uv”中,“1204282”是数字部分,“uv”是单位标识(代表微伏)。去除单位后,我们专注于数字转换。 - 在引用[^2]中,DTS 属性如 `press-threshold-microvolt = <33000>;` 的值就是以微伏为单位的整数形式,没有单位后缀。但在您的输入中,字符串包含单位,因此可能需要先解析数字部分[^2]。 ### 步骤 2: 执行转换计算 - 给定值:$\mu V = 1204282$ - 转换为伏特:$ V = \frac{1204282}{1000000} $ - 计算结果: - $ 1204282 \div 1000000 = 1.204282 $ - 因此,1204282 微伏 = 1.204282 伏特。 - 移除单位后:数值结果为 **1.204282**(这是纯数字,没有单位)。 ### 步骤 3: 在 Android 开发中的处理建议 - 如果您是处理类似引用[^2]中的场景(如设备树文件或驱动程序中的电压值),在 Android 内核代码中,电压值通常以整数(微伏)形式存储,单位是隐含的(例如属性名如 `press-threshold-microvolt` 已指定单位)。但如果您遇到了字符串形式(如日志或配置文件中的“1204282uv”),建议用代码解析: - **解析和转换示例(Java 或 C)**: - 使用字符串处理函数提取数字部分(例如,移除“uv”后缀)。 - 将字符串转换为数值类型(如整数或浮点数)。 - 执行除 1000000.0 的操作得到伏特值。 - 输出时,只保留数字部分。 - 简单伪代码(以 Java 为例,适用于 Android 应用层): ```java String input = "1204282uv"; // 移除单位后缀,提取数字部分 String numericPart = input.replace("uv", "").trim(); // 转换为浮点数并转换单位 float microvolts = Float.parseFloat(numericPart); float volts = microvolts / 1000000.0f; // 输出去除单位后的数字(如 1.204282) System.out.println(volts); ``` - 在 C 代码中(适用于 Android 内核开发,如驱动程序),电压值通常直接使用整数操作: ```c int microvolts = 1204282; // 从字符串解析的数字,单位为微伏 double volts = (double)microvolts / 1000000.0; // 转换为伏特 printf("%f", volts); // 输出: 1.204282 ``` - **为什么重要?** 在引用[^2]和[^1]中,电压阈值(如 `press-threshold-microvolt`)用于按键检测逻辑(例如,耳机监测或音量键)。转换后,您可能在系统调试、功耗优化或事件处理中使用伏特值(如引用[^3]提到的 CPUFreq 调整电压以降低功耗)。但单位转换是基础步骤,确保值精确用于后续计算[^1][^2][^3]。 ### 最终结果 输入“1204282uv”转换为伏特并移除单位后,数字值为:**1.204282**。 (这可以直接用于编程或数学计算。)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值