版权声明:android
本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。算法
未经容许,不得转载。3d
Android 系统的智能电视,最近两年基本上愈来愈火了,而在如今手机 App 开发中,都是使用触摸的模式进行操做,可是在开发智能电视 App 的时候,View 的焦点寻址,就是咱们绕不过去的坎。cdn
那么,本文就 View 如何控制 Focus,来分析它背后的实现逻辑。blog
在 Android 中,是有一套本身的焦点查找的算法,简单来讲,就近原则,就是按方向就近查找下一个符合条件的 View。接口
若是咱们有对一个 View 焦点控制的需求,须要对这个 View 强制指定它上下左右以后的下一个获取焦点的 View。能够经过 View 的属性来控制,只须要在对应方向上设定咱们须要焦点转移的下一个 View 的 ID 便可。ci
这些都是最基本的,不是本文的主题。那么若是没有设定这些属性,而 Android 对 View 的就近原则的焦点查找算法,究竟是如何实现的呢?开发
Android 中,是如何作到对 View 焦点的控制呢?源码
咱们就先从 View 的源码看起,看看它是如何找到“下一个”位置的 View的,在 View 中,查找下一个应该获取焦点的 View ,使用的方法是 focusSearch()。it
它须要传递一个 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() 方法,只使用属性控制也能知足咱们的需求。