Android TV 按键焦点事件分发流程详解

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android TV 按键焦点事件分发流程详解相关的知识,希望对你有一定的参考价值。

参考技术A

DecorView →PhoneWindow →Activity→ViewGroup→view

下面我们根据按键事件的分发流程,抽丝剥茧,逐一分析。

private int processKeyEvent(QueuedInputEvent q)

1、DecorView.java

2、Activity.java

3、ViewGroup.java

4、View.java

通过该方法,接收器receiver的onKeyDown、onKeyUp、onKeyLongPress、onKeyMultiple等方法将被回调。

在上述按键事件的入口中提到的ViewRootImpl中

如果mView.dispatchKeyEvent(event)返回true,则结束事件分发;
如果返回false,则调用如下方法

继续执行后续的焦点导航流程。
焦点导航的总体流程就是:
1、View focused = mView.findFocus();//从视图树的顶层,即DecorView一层一层的递归查找当前获得焦点的view
2、View v = focused.focusSearch(direction);根据导航的方向查找下一个可获取焦点的view
3、v.requestFocus(direction, mTempRect)请求获取焦点
4、v.requestFocus(direction,mTempRect)内部,调用mParent.requestChildFocus(this, focused)逐层递归向上级通知

ViewRootImpl.java

mView即DecorView,从DecorView开始,一层一层的向下递归查找当前获得焦点的view

找到了当前获得焦点的focused,调用该焦点view的focusSearch(direction)方法查找direction方向上下一个将要获取焦点的view。
focused.focusSearch(direction)实际上会调用mParent.focusSearch(this, direction)方法,层层递归,直到调用到DecorView的focusSearch(this, direction)方法。
而DecorView继承ViewGroup,实际上最终会调用到FocusFinder.getInstance().findNextFocus(this, focused, direction),this 就是DecorView对象。

最终会调用到DecorView父类ViewGroup中的FocusFinder.getInstance().findNextFocus(this, focused, direction);

ViewGroup.java

FocusFinder.java

搜索到下一个获取焦点的view后,调用该view.requestFocus(direction, mTempRect)方法
注意:调用requestFocus(direction, mTempRect)需要区分调用者。
如果是ViewGroup,则会更加焦点获取策略,实现父View和子View之间获取焦点的优先级。
如下是ViewGroup.java 和View.java 中requestFocus方法是实现:

ViewGroup.java

View.java

View获取到焦点后,会调用mParent.requestChildFocus(this, focused)逐层递归向上级通知
ViewGroup.java

Android TV 焦点与按键事件分析

转自:http://blog.csdn.net/yummykwok/article/details/56667260


在触摸屏出现在手机上之前,焦点是手机上人机交互中最重要的一个概念。焦点即用户当前的关注点(或区域),手机上将该区域以某种形式高亮显示,人们通过上、下、左、右方向键可以移动焦点,按确认键后手机将打开(或呈显)与当前焦点关联的内容;触摸屏的出现大大地简化了人机交互,触摸事件(TouchEvent)成了核心,焦点的存在感就很小了。

       但是对于电视来说,其显示屏面积大,人机距离远,触摸屏的方案显然不合理。因此目前Android电视的人机交互仍旧使用遥控器为主,焦点的重要性在电视上又显现出来了。通过遥控器将方向键或确认键信号(或信息)发送到电视端后,转换为标准按键事件(KeyEvent),而按键事件分发最终目标就是焦点。


1、初识View之焦点

ViewUI组件的基本构建,也自然就是焦点的承载者。View是否可聚焦,由FOCUSABLEFOCUSABLE_IN_TOUCH_MODE(触摸模式下也可以有焦点)两个FLAG标识。

[java]  view plain  copy
  1. public View(Context context, @Nullable AttributeSet attrs, int defStyleAttr, int defStyleRes)   
  2.     this(context);  
  3.     final TypedArray a = context.obtainStyledAttributes(  
  4.             attrs, com.android.internal.R.styleable.View, defStyleAttr, defStyleRes);  
  5.     final int N = a.getIndexCount();  
  6.     for (int i = 0; i < N; i++)   
  7.         int attr = a.getIndex(i);  
  8.         switch (attr)   
  9.             ……  
  10.             case com.android.internal.R.styleable.View_focusable:  
  11.                 if (a.getBoolean(attr, false))   
  12.                     viewFlagValues |= FOCUSABLE;  
  13.                     viewFlagMasks |= FOCUSABLE_MASK;  
  14.                   
  15.                 break;  
  16.             case com.android.internal.R.styleable.View_focusableInTouchMode:  
  17.                 if (a.getBoolean(attr, false))   
  18.                     viewFlagValues |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE;  
  19.                     viewFlagMasks |= FOCUSABLE_IN_TOUCH_MODE | FOCUSABLE_MASK;  
  20.                   
  21.                 break;  
  22.             ……  
  23.           
  24.       
  25.     ……  
  26.   

从上面  View  的构建方法上看,在 xml  里即可为其设置是否可聚焦,以  Button  举个栗子,

[java]  view plain  copy
  1. public class Button extends TextView   
  2.     ……  
  3.     public Button(Context context, AttributeSet attrs)   
  4.         this(context, attrs, com.android.internal.R.attr.buttonStyle);  
  5.       
  6.     ……  
  7.   

Button设置了一个默认的style,我们找出源码看看,

[html]  view plain  copy
  1. <stylenamestylename="Widget.Button">  
  2.     <itemnameitemname="background">@drawable/btn_default</item>  
  3.     <strong><itemnameitemname="focusable">true</item></strong>  
  4.     <itemnameitemname="clickable">true</item>  
  5.     <itemnameitemname="textAppearance">?attr/textAppearanceSmallInverse</item>  
  6.     <itemnameitemname="textColor">@color/primary_text_light</item>  
  7.     以上是关于Android TV 按键焦点事件分发流程详解的主要内容,如果未能解决你的问题,请参考以下文章

    Android TV按键焦点原理浅谈

    Android焦点事件分发与传递机制

    Android TV 焦点与按键事件分析

    Android TV 焦点与按键事件分析

    Android焦点事件分发与传递机制

    安卓Tv开发移动智能电视之焦点控制(按键事件)