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


正文共: 1987字 11图

预计阅读时间: 5分钟

一、前言

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() 方法,只使用属性控制也能满足我们的需求。

你尝试过 Android TV App 吗?有什么遇到什么坑?可以在留言区我们讨论讨论!

今天在承香墨影公众号的后台,回复『成长』。我会送你一些我整理的学习资料,包含:Android反编译、算法、设计模式、虚拟机、Linux、Kotlin、Python、爬虫、Web项目源码。

送书活动最后一天,人人都有机会

推荐阅读:

听说喜欢分享的人,运气都不会太差

点击『阅读原文』查看更多精彩内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值