Android View 焦点寻址的来龙去脉 !!!

企业动态
Android 系统的智能电视,最近两年基本上越来越火了,而在现在手机 App 开发中,都是使用触摸的模式进行操作,但是在开发智能电视 App 的时候,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专栏作者“张旸”的原创稿件,转载请通过微信公众号联系作者获取授权】

戳这里,看该作者更多好文

责任编辑:武晓燕 来源: 51CTO专栏
相关推荐

2016-12-12 09:58:47

AndroidAndroid Vie

2021-07-07 11:35:17

Linux内存段寻址

2011-01-26 10:21:30

view类Qt

2022-06-28 18:32:45

物联网IoT

2009-06-26 08:44:57

2018-01-09 04:59:59

VLANTag网络技术

2021-10-08 07:53:01

Go 寻址元素

2019-10-31 08:36:59

线程内存操作系统

2021-05-13 10:12:55

Kubernetes 微服务软件开发

2022-08-02 09:02:17

虚拟内存操作系统

2021-01-19 11:40:40

Linux代码程序编译

2022-06-09 09:20:40

Linux语言编写代码

2009-10-20 14:58:15

Javascript事

2020-09-30 06:50:35

Linux内存寻址

2020-04-12 22:23:45

Kubernetes容器网络

2018-02-24 13:21:02

2011-08-30 16:26:34

Hadoop

2011-12-23 10:17:25

Android音乐编程管理音频焦点

2019-08-02 08:59:21

Token认证服务器

2020-04-15 22:18:55

架构负载均衡分布式
点赞
收藏

51CTO技术栈公众号