KeyEvent分发机制

本文详细探讨了Android TV中KeyEvent的分发机制,重点在于如何截断和消耗事件。讲解了Activity的dispatchKeyEvent方法以及子View的dispatchKeyEvent流程,强调了在重写dispatchKeyEvent时返回父类方法的重要性,以确保事件能正确分发。同时,解释了OnKeyListener在事件处理中的角色,以及在不同情况下如何阻止事件进一步分发。

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

先说重要点:
要点一: 截断事件

TV:通过 dispatchKeyEvent 分发事件,返回 false 或者 true 截断本类和子类中的事件分发(onKeyDown无法接收到事件),截取某个按键可返回 false 和 ture 都能截断这个按键向下分发,对上层没有影响。

​Phone:和上同理知识分发事件的方法为 dispatchTouchEvent ,由onTouchEvent 处理。

要点二: 消耗事件

​ KeyEvent 事件处理只有两个地方,一个是 Activity,另一个则是具体的View,返回true 表示事件已消耗,返回 false 则表示事件还在。

​ 当KeyEvent 事件分到具体的子 View 的 dispatchEvent() 里时,View 回去先去看有没有设置 OnKeyListener监听器吗,有则回调 OnKeyListener.onKey()方法来处理事件,当返回 false 或者为空的时候,VIew会通过调用KeyEvent的dispatch()来回调View自己的onKeyDown/Up()来处理事件。

调用使用 OnKeyListener 监听器👇

MButton mButton = new MButton(this);
//如果不设置 OnKeyListener 监听器,事件将由 onKeyDown() 方法处理事件
mButton.setOnKeyListener(new View.OnKeyListener() {
   
   
    @Override
    public boolean onKey(View v, int keyCode, KeyEvent event) {
   
   
        return false;
    }
});

如果不想一个事件执行两次,就返回 true

要点二:

​ 如果你在本类中重写了dispatchKeyEvent 方法,记得返回父类的 dispatchKeyEvent(return super.dispatchKeyEvent),因为你重写的 dispatchKeyEvent 没有事件分发,这会导致下面调用的无法接收到事件,相当于截取了全部事件。

运行流程:

请添加图片描述

(PhoneWindow$)DecorView的dispatchKeyEvent

@Override
public boolean dispatchKeyEvent(KeyEvent event) {
   
   
    final int keyCode = event.getKeyCode();
    final int action = event.getAction();
    final boolean isDown = action == KeyEvent.ACTION_DOWN;

    if (isDown && (event.getRepeatCount() == 0)) {
   
   
        // First handle chording of panel key: if a panel key is held
        // but not released, try to execute a shortcut in it.
        if ((mWindow.mPanelChordingKey > 0) && (mWindow.mPanelChordingKey != keyCode)) {
   
   
            boolean handled = dispatchKeyShortcutEvent(event);
            if (handled) {
   
   
                return true;
            }
        }

        // If a panel is open, perform a shortcut on it without the
        // chorded panel key
        if ((mWindow.mPreparedPanel != null) && mWindow.mPreparedPanel.isOpen) {
   
   
            if (mWindow.performPanelShortcut(mWindow.mPreparedPanel, keyCode, event, 0)
Android 事件分发机制是指在用户与Android设备进行交互时,Android系统如何接收并分发这些事件的过程。事件分发机制包括三个阶段:分发、拦截和处理。 1. 分发阶段:事件从Android设备的底层硬件驱动程序开始,通过InputEvent分发给View层。在View层中,事件分为两类:MotionEvent和KeyEvent。MotionEvent表示触摸事件,包括按下、移动、抬起等操作;KeyEvent表示按键事件,包括按下和抬起。 2. 拦截阶段:在事件分发到View层后,会从最上层的View开始进行事件分发,直到有View对事件进行拦截。如果有View对事件进行了拦截,则事件不会继续向下分发,而是由该View进行处理。View是否拦截事件的判断由onInterceptTouchEvent方法完成,如果该方法返回true则表示拦截事件。 3. 处理阶段:如果事件没有被拦截,则会被传递到最底层的View进行处理。在View中,事件处理由onTouchEvent方法完成。如果该方法返回true,则表示事件已经被处理,不再需要继续向下分发;如果返回false,则会继续向上分发直到有View对事件进行拦截。 Android事件分发机制的流程如下: ![image.png](attachment:image.png) 需要注意的是,事件分发机制是一个逆向分发的过程,即从底层向上分发,而不是从顶层向下分发。这是因为底层的View需要先处理事件,如果底层的View不拦截事件,事件才能向上分发
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值