Android TV 的焦点移动原理

本文探讨了Android TV中焦点移动的重要性和基本用法,包括如何设置控件的可聚焦性,以及焦点移动的XML属性。文章深入源码,分析了在处理KeyEvent时焦点如何在View之间传递,并详细阐述了focusSearch方法的工作原理,解释了焦点视图查找的算法和可能遇到的问题。
摘要由CSDN通过智能技术生成

焦点:

 

焦点(Focus)可以理解为选中态,在Android TV上起很重要的作用。一个视图控件只有在获得焦点的状态下,才能响应按键的Click事件。

上图中,外面有一个绿色光圈的视图,就是当前有焦点的视图。

相对于手机上用手指点击屏幕产生的Click事件, 在使用Android TV的过程中,遥控器是一个主流的操作工具,通过点击遥控器的方向键来控制焦点的移动。当焦点移动到目标控件上之后,按下遥控器的确定键,才会触发一个Click事件,进而去做下一步的处理。焦点的移动如下图所示。

基础的用法:

在处理焦点的时候,有一些基础的用法需要知道。

首先,isFocusable()需要为true,一个控件才有资格可以获取到焦点,可以通过setFocusable(boolean)方法来设置。如果想要在触摸模式下获取焦点(在我们用手机开发的过程中),需要isFocusableInTouchMode()为true,可以通过setFocusableInTouchMode(boolean)来设置。也可以直接在xml布局文件中指定:

<Button
    ...
    android:focusable="true"
    android:focusableInTouchMode="true"/>

复制

然后,就是控制焦点的移动了。在谷歌官方文档中提到:

焦点移动的时候(默认的情况下),会按照一种算法去找在指定移动方向上最近的邻居。在一些情况下,焦点的移动可能跟开发者的意图不符,这时开发者可以在布局文件中使用下面这些XML属性来指定下一个焦点对象:

nextFocusDown
nextFocusLeft
nextFocusRight
nextFocusUp 

复制

在Java代码中,让一个指定的View获取焦点,可以调用它的requestFocus()方法。

遇到的问题:

尽管有了官方文档中提到的基础用法,但是在进行Android TV开发的过程中,还是经常会遇到一些焦点方面的问题或者疑问,如

  • “明明指定了焦点id,焦点却跑丢了”
  • “onKeyDown里居然截获不到按键事件”
  • “我没有做任何焦点处理,焦点是怎么自己跑到那个View上的”

接下来,带着这些问题,我们就从源码的角度出发,简单分析一下焦点的移动原理。本文以API 23作为参考。

KeyEvent

在手机上,当手指触摸屏幕时,会产生一个的触摸事件,MotionEvent,进而完成点击,长按,滑动等行为。

而当按下遥控器的按键时,会产生一个按键事件,就是KeyEvent,包含“上”,“下”,“左”,“右”,“返回”,“确定”等指令。焦点的处理就在KeyEvent的分发当中完成。

首先,KeyEvent会流转到ViewRootImpl中开始进行处理,具体方法是内部类ViewPostImeInputStage中的processKeyEvent。(在API 17之前,是deliverKeyEventPostIme这个方法,逻辑大体一致,本文仅以processKeyEvent作为参考)

private int processKeyEvent(QueuedInputEvent q) {
        final KeyEvent event = (KeyEvent)q.mEvent;
        ...
        // Deliver the key to the view hierarchy.
        // 1. 先去执行mView的dispatchKeyEvent
        if (mView.dispatchKeyEvent(event)) {
            return FINISH_HANDLED;
        }
        ...
        // Handle automatic focus changes.
        if (event.getAction() == KeyEvent.ACTION_DOWN) {
            int direction = 0;
            .
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值