Android 的 View 焦点寻址

版权声明:android

本帐号发布文章均来自公众号,承香墨影(cxmyDev),版权归承香墨影全部。算法

未经容许,不得转载。3d

1、前言

Android 系统的智能电视,最近两年基本上愈来愈火了,而在如今手机 App 开发中,都是使用触摸的模式进行操做,可是在开发智能电视 App 的时候,View 的焦点寻址,就是咱们绕不过去的坎。cdn

那么,本文就 View 如何控制 Focus,来分析它背后的实现逻辑。blog

2、View 的焦点控制

在 Android 中,是有一套本身的焦点查找的算法,简单来讲,就近原则,就是按方向就近查找下一个符合条件的 View。接口

若是咱们有对一个 View 焦点控制的需求,须要对这个 View 强制指定它上下左右以后的下一个获取焦点的 View。能够经过 View 的属性来控制,只须要在对应方向上设定咱们须要焦点转移的下一个 View 的 ID 便可。ci

  • android:nextFocusDown:按下的时候,焦点寻址的 ViewId。
  • android:nextFocusUp:按上的时候,焦点寻址的 ViewId。
  • android:nextFocusLeft:按左的时候,焦点寻址的 ViewId。
  • android:nextFocusRight:按右的时候,焦点寻址的 ViewId。
  • android:nextFocusForward:向前的时候,焦点寻址的 ViewId。

这些都是最基本的,不是本文的主题。那么若是没有设定这些属性,而 Android 对 View 的就近原则的焦点查找算法,究竟是如何实现的呢?开发

3、View 的焦点寻址

Android 中,是如何作到对 View 焦点的控制呢?源码

咱们就先从 View 的源码看起,看看它是如何找到“下一个”位置的 View的,在 View 中,查找下一个应该获取焦点的 View ,使用的方法是 focusSearch()。it

f-fsearch.png

它须要传递一个 direction 参数,这个 direction 就是指定获取什么方向上的下一个位置的焦点。

而 View 并不会处理焦点寻址的具体逻辑,而是将焦点的查找委托给 mParent 来实现,mParent 是一个接口,它的实现类是 ViewRootImpl。

f-vsearch.png

ViewRootImlp.focusSearch() 最终又将焦点寻址的任务,交托给 FocusFinder 来处理。

f-nextSearch.png

findNextFocus() 中能够看到,findNextUserSpecifiedFocus() 方法正是用于查找咱们对 View 设定不一样方向的下一个焦点的 ViewId ,它的优先级是最高的,若是没有找到,才会进行 findNextFocus() 经过算法来查找对应的 View。

为了证明这个说法,咱们先看看 findNextUserSpecifiedFocus() 的源码。

f-user.png

最终,又调回到 View.findUserSetNextFocus() 方法去寻找。

f-viewuser.png

到这里也证明了咱们的猜想,确实是经过 direction 来进行 View 的焦点寻址。

再回过头来看看 findNextFocus() 方法,若是经过 findNextUserSpecifiedFocus() 方法没有找到咱们指定的 View,就会继续向下执行。这里声明的一个局部变量 focusables 就是用于存放符合算法的全部 View 。

接下来再看看如何向 focusables 这个 List 中,添加符合寻址要求的 View。在 findNextFocus() 中能够看到,它最终会调用 findNextFocusInAbsoluteDirection() 方法。

f-findnext.png

从 findNextFocusInAbsoluteDirection() 方法能够看出,就近原则就是在这里实现的,经过 View 的坐标点,计算出最符合要求的 View ,最终将找到的 View 返回过去。

f-abs.png

到这里,基本就追踪到 View 对焦点寻址的完整逻辑。最后补一个方法调用的流程图。

f-tu.png

4、总结

若是有对 View 焦点的控制,能够考虑经过设置 View 的属性,还能够经过重写 View.focusSearch() 方法,来定制 View 焦点的寻址规则。不过通常而言,不推荐重写 focusSearch() 方法,只使用属性控制也能知足咱们的需求。

公众号二维码.jpg
相关文章
相关标签/搜索