android press 事件监测

在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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值