Android View 焦点寻址的来龙去脉 !!! | 您所在的位置:网站首页 › 街舞劲爆视频 › Android View 焦点寻址的来龙去脉 !!! |
[[214996]] 一、前言 Android 系统的智能电视,最近两年基本上越来越火了,而在现在手机 App 开发中,都是使用触摸的模式进行操作,但是在开发智能电视 App 的时候,View 的焦点寻址,就是我们绕不过去的坎。 那么,本文就 View 如何控制 Focus,来分析它背后的实现逻辑。 二、View 的焦点控制 在 Android 中,是有一套自己的焦点查找的算法,简单来说,就近原则,就是按方向就近查找下一个符合条件的 View。 如果我们有对一个 View 焦点控制的需求,需要对这个 View 强制指定它上下左右之后的下一个获取焦点的 View。可以通过 View 的属性来控制,只需要在对应方向上设定我们需要焦点转移的下一个 View 的 ID 即可。 android:nextFocusDown:按下的时候,焦点寻址的 ViewId。 android:nextFocusUp:按上的时候,焦点寻址的 ViewId。 android:nextFocusLeft:按左的时候,焦点寻址的 ViewId。 android:nextFocusRight:按右的时候,焦点寻址的 ViewId。 android:nextFocusForward:向前的时候,焦点寻址的 ViewId。这些都是最基本的,不是本文的主题。那么如果没有设定这些属性,而 Android 对 View 的 就近原则 的焦点查找算法,到底是如何实现的呢? 三、View 的焦点寻址 Android 中,是如何做到对 View 焦点的控制呢? 我们就先从 View 的源码看起,看看它是如何找到“下一个”位置的 View的,在 View 中,查找下一个应该获取焦点的 View ,使用的方法是 focusSearch()。 它需要传递一个 direction 参数,这个 direction 就是指定获取什么方向上的下一个位置的焦点。 而 View 并不会处理焦点寻址的具体逻辑,而是将焦点的查找委托给 mParent 来实现,mParent 是一个接口,它的实现类是 ViewRootImpl。 ViewRootImlp.focusSearch() 最终又将焦点寻址的任务,交托给 FocusFinder 来处理。 findNextFocus()中可以看到,findNextUserSpecifiedFocus() 方法正是用于查找我们对 View 设定不同方向的下一个焦点的 ViewId ,它的优先级是***的,如果没有找到,才会进行 findNextFocus() 通过算法来查找对应的 View。 为了证实这个说法,我们先看看 findNextUserSpecifiedFocus()的源码。 最终,又调回到 View.findUserSetNextFocus() 方法去寻找。 到这里也证实了我们的猜测,确实是通过 direction 来进行 View 的焦点寻址。 再回过头来看看 findNextFocus() 方法,如果通过 findNextUserSpecifiedFocus() 方法没有找到我们指定的 View,就会继续向下执行。这里声明的一个局部变量 focusables 就是用于存放符合算法的所有 View 。 接下来再看看如何向 focusables 这个 List 中,添加符合寻址要求的 View。在 findNextFocus() 中可以看到,它最终会调用 findNextFocusInAbsoluteDirection() 方法。 从 findNextFocusInAbsoluteDirection() 方法可以看出,就近原则就是在这里实现的,通过 View 的坐标点,计算出***要求的 View ,最终将找到的 View 返回过去。 到这里,基本就追踪到 View 对焦点寻址的完整逻辑。***补一个方法调用的流程图。 四、总结 如果有对 View 焦点的控制,可以考虑通过设置 View 的属性,还可以通过重写 View.focusSearch() 方法,来定制 View 焦点的寻址规则。不过一般而言,不推荐重写 focusSearch() 方法,只使用属性控制也能满足我们的需求。 【本文为51CTO专栏作者“张旸”的原创稿件,转载请通过微信公众号联系作者获取授权】 戳这里,看该作者更多好文 |
CopyRight 2018-2019 实验室设备网 版权所有 |