按键分析--APP部分-- OnLongClickListener事件处理流程

来源:互联网 发布:qq浏览器链接不了网络 编辑:程序博客网 时间:2024/05/17 14:25

5.4         OnLongClickListener事件处理流程

 

 

5.4.1         OnLongClickListener注册和使用

其注册和使用方法和OnClickListener相似,在activity里实现接口,

public class Launcher extends Activity

        implements View.OnLongClickListener,

 

view设置监听器,

        mWorkspace.setOnLongClickListener(this);

 

view基类里调用performLongClick,执行onLongClick()

    public boolean performLongClick() {

        sendAccessibilityEvent(AccessibilityEvent.TYPE_VIEW_LONG_CLICKED);

 

        boolean handled = false;

        ListenerInfo li = mListenerInfo;

        if (li != null && li.mOnLongClickListener != null) {

            handled = li.mOnLongClickListener.onLongClick(View.this);

        }

        if (!handled) {

            handled = showContextMenu();

        }

        if (handled) {

            performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);

        }

        return handled;

    }

 

 

5.4.2         OnClickListener栈分析

栈的调用过程和OnClickListener也类似,用异步的方式调用到activity的onLongClick方法,

Launcher.onLongClick(View) line: 5169     

CellLayout(View).performLongClick() line: 5244      

View$CheckForLongPress.run() line: 21138

Handler.handleCallback(Message) line: 739 

ViewRootImpl$ViewRootHandler(Handler).dispatchMessage(Message) line: 95      

Looper.loop() line: 148 

ActivityThread.main(String[]) line: 5524    

Method.invoke(Object, Object...) line: not available [native method]

ZygoteInit$MethodAndArgsCaller.run() line: 752      

ZygoteInit.main(String[]) line: 642     

 

 

所以我们看一下消息是如何post出来的即可。

 

Android的触摸消息中,已经实现了三种监测,它们分别是

1)pre-pressed:对应的语义是用户轻触(tap)了屏幕

2)pressed:对应的语义是用户点击(press)了屏幕

3)long pressed:对应的语义是用户长按(long press)了屏幕

下图是触摸消息随时间变化的时间轴示意图:

其中,t0和t1定义在ViewConfiguration类中,标识了tap和longpress的超时时间,定义如下:

private static final int TAP_TIMEOUT = 100;

private static final int DEFAULT_LONG_PRESS_TIMEOUT = 500;

 

在早期版本中,在View类的OnTouchEvent函数中,当View监测到ACTION_DOWN事件时,首先发送一个延迟为t0的异步消息处理tap,在Android6.0中则不使用这种机制了。

 

长按的调用栈:

onTouchEvent --checkForLongClick –post

—CheckForLongPress--run --performLongClick-- .mOnLongClickListener.onLongClick

 

如前分析,在onTouchEvent的MotionEvent.ACTION_DOWN,执行checkForLongClick,延时post一个长按消息出去。

                case MotionEvent.ACTION_DOWN:

                    mHasPerformedLongPress = false;

                    // Walk up the hierarchy to determine if we're inside a scrolling container.

                    boolean isInScrollingContainer = isInScrollingContainer();

 

                    // For views inside a scrolling container, delay the pressed feedback for

                    // a short period in case this is a scroll.

                    if (isInScrollingContainer) {

                        mPrivateFlags |= PFLAG_PREPRESSED;

                        if (mPendingCheckForTap == null) {

                            mPendingCheckForTap = new CheckForTap();

                        }

                        mPendingCheckForTap.x = event.getX();

                        mPendingCheckForTap.y = event.getY();

                        postDelayed(mPendingCheckForTap, ViewConfiguration.getTapTimeout());

                    } else {

                        // Not inside a scrolling container, so show the feedback right away

                        setPressed(true, x, y);

                        checkForLongClick(0);

                    }

                    break;

 

 

在MotionEvent.ACTION_UP及MOVE\CANCEL中, 会清除长按的异步消息,设置相关的变量和按键状态,这样,如果这些事件产生在长按超期前,长按就不起作用;在长按超期后,长按有效,并完成了按键的周期流程。所以按键处理的逻辑就是这样的。

                 removeLongPressCallback();

 

                 setPressed(false);

 

 onClick和onLongClick能同时发生吗?

要理解Android对事件处理的所谓消费(consume)概念即可,一个用户的操作会被传递到不同的View控件和同一个控件的不同监听方法处理,任何一个接收并处理了该次事件的方法如果在处理完后返回了true,那么该次event就算被完全处理了,其他的View或者监听方法就不会再有机会处理该event了。

     onLongClick的发生是由单独的线程完成的,一般发生在ACTION_UP之前,而onClick的发生是在ACTION_UP后。临界条件是同时发生,这里会有flag来进行区分。

因此同一次用户touch操作就有可能既发生onLongClick又发生onClick。

及时向系统表示“我已经完全处理(消费)了用户的此次操作”,是很重要的事情。

另外一个同时执行的概念(都执行的意思),先后执行,例如,我们如果在onLongClick()方法的最后return true,那么onClick事件就没有机会被触发了。

 

在onLongClick()方法return false的情况下,一次触碰操作的基本时序:

04-05 06:00:53.023: DEBUG/TSActivity(277): onTouch ACTION_DOWN

04-05 06:00:53.533: DEBUG/TSActivity(277): onLongClick 

04-05 06:00:55.603: DEBUG/TSActivity(277): onTouch ACTION_UP

04-05 06:00:55.663: DEBUG/TSActivity(277): onClick

可以看到,在ACTION_UP后仍然触发了onClick()方法。

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 淘宝店被扣24分怎么办 实体店铺查封后怎么办 淘宝店铺封订单怎么办 淘宝店铺被扣分怎么办 淘宝账户被保护怎么办 k宝登录不了怎么办 手机淘宝看不到图片怎么办 淘宝拿到货退款怎么办 商家收货未退款怎么办 卖家发了货退款怎么办 淘宝退款货到了怎么办 退货退款不退货怎么办 换手机了淘宝怎么办 换了手机号淘宝怎么办 支付宝不能收款怎么办 换号码了淘宝怎么办 支付宝付款码打不开怎么办 苹果付款信息打不开怎么办 地税密码忘记了怎么办 网上开店没订单怎么办 qq群人员上限怎么办 糖果y9桌面锁定怎么办 手机桌面乱了怎么办 网页内容不能复制怎么办 网页不能复制粘贴怎么办 闲鱼收到假货怎么办 微博账户锁定怎么办 闲鱼东西被下架怎么办 无锡梅村社保卡怎么办 无锡梅村医保卡怎么办 常州不要的旧家具怎么办 闲退款不退货怎么办 小白摄像机离线怎么办 oppo手机死机了怎么办 手机关机卡住了怎么办 手机死机无法关机怎么办 华为听筒音量小怎么办 小米手机自动接听电话怎么办 手机sd不兼容怎么办 安装包安装失败怎么办 三星s7edge闪退怎么办