继按键事件的一次踩坑记录

前言

作为我们一代码农,没事多踩坑才能看到不一样的东西,可以说是踩踩更健康。为了给这一次的踩坑留下一点回忆,特此开启我的博客旅程。本次踩坑经历是在安卓TV上面处理按键事件,希望对大家会有一点点的帮助。


分发流程

KeyEvent 在一个 View 树内部的分发处理流程,简单点说,也就是,你在某个 Activity 界面点击了遥控器的某个按键,然后这个按键事件在当前这个 Activity 里是如何分发处理的。

继按键事件的一次踩坑记录

整体流程:(PhoneWindow$)DecorView -> dispatchKeyEvent()
Activity -> dispatchKeyEvent()
ViewGroup -> dispatchKeyEvent()
View -> dispatchKeyEvent()
KeyEvent -> dispatch()
View -> onKeyDown/Up()

当我们在activity中按下遥控器的一个按键时,会产生action_down/up 两个event事件分发,最终交由activity或者view处理。

当接收到 KeyEvent 事件时,首先是交给 (PhoneWindow$)DecorView 的 dispatchKeyEvent() 分发,而 DecorView 会去调用 Activity 的 dispatchKeyEvent(),交给 Activity 继续分发。
继按键事件的一次踩坑记录
Activity 会先获取 PhoneWindow 对象,然后调用 PhoneWindow 的superDispatchKeyEvent(),PhoneWindow 转而调用 DecorView 的 superDispatchKeyEvent(),而 DecorView 则调用了 super.dispatchKeyEvent() 将事件交给父类分发, DecorView 继承自 FrameLayout,但 FrameLayout 没有实现 dispatchKeyEvent(),所以实际上是交给 ViewGroup 的 dispatchKeyEvent() 来分发。

具体方法流程

事件经由DecorView 传递Activity的dispatchKeyEvent(),一般在做TV按键处理时,会这这一层级进行一些特殊的拦截处理,return true.如果没有拦截处理 event事件会记下向下传递给Activity中的view去响应事件处理,如果view设置响应事件setonkeylistener()事件的话(此处view需要有获焦的能力),事件会响应在view 的onkeydown/up() 方法不会再响应activity的onkeyup/down()方法。(此次踩坑点)反之view没有设置按键监听事件的话,最终event事件会响应activity的onkeydown/up()方法。

继按键事件的一次踩坑记录

在activity 的onkeydown/up()方法中我们对应可以根据获取按键响应次数来判断一些特殊的按键操作,比如我们经常会用的的长按事件处理,不过对应的一些view的长按处理可以使用setonlongclicklistener()方法进行处理,很方便。

 

最后总结

当我们处理一些按键事件的时候,如果遇到一些莫名其妙的响应方法没有走的话,这个时候不要觉得好奇怪啊,怎么不走那。想一想静静,这个时候你可能就会发现,哎呀这个事件怎么被这个view给截胡了那,我要把你修理一顿。然后整个方法流程就乖乖的走通了。。。