AndroidTv Home界面实现原理(二)——Leanback 库的主页卡位缩放动画源码解析
本篇文章已授权微信公众号 dasu_Android(大苏)独家发布
先看个效果图:
上一篇中,我们留了问题,在 Tv Home 界面这种很常见聚焦卡位放大动画效果,我们这一篇就来看看 Leanback 库是怎么实现的。
如果要我们自己实现的话,思路应该不难,就是写个放大、缩小动画,然后在卡位获得焦点时应用放大动画,失去焦点时应用缩小动画,所以关键点只是在于如何进行封装。那下面就来学学 Google Leanback 库的 ItemView 缩放动画的实现思路。
源码分析
看源码时,我习惯带着目的性地去阅读,这样只要专注于理解跟目的相关的代码即可,不用每行代码地去分析,毕竟好多代码目前能力有限,还啃不透。
那么,我们这次阅读源码的目的就是要搞清楚:卡位获得焦点时放大、缩小动画是如何实现的?
阅读源码时经常会碰到一个问题,那就是该从哪入手,从哪开始看?
这就是为什么我习惯带着目的去阅读,因为我们可以从目的分析,猜测我们需要的代码应该在哪里,然后找到我们该从哪里阅读,再一步步的去分析。
比如我们这次的任务,我们该从哪里入手阅读源码呢?首先,你得先了解一下 Leanback 库的基本使用,这就是为什么我第一篇博客先简单介绍了 Leanback 库的使用。在上一篇博客里,可以看到,我们跟 Leanback 库打交道的也就是下面这几个类:
- ArrayObjectAdapter:作用类似于 List,装填着整个页面的数据,页面数据其实是分两级,以行为单位和以每一行中的 Item 为单位,所以整个页面有一个 ArrayObjectAdapter(mRowsAdapter) 对象,它由许多行数据 ArrayObjectAdapter(rowAdapter) 对象组成,每行数据 rowAdapter 由许多 Item 组成。初始化一个 ArrayObjectAdapter 对象时,必须提供一个 Presenter 对象与它关联。
- ListRowPresenter:Leanback 库中的 Presenter 作用都有些类似于 RecyclerView.Adapter,用于创建 ItemView 以及将数据绑定到 ItemView 上。
- ListRow:可以理解成一个 Mode,也就是把每一行抽象封装成一个 ListRow
- BrowerFragment:用来展示可左右上下滑动的视频列表界面,Leanback 已高度封装,我们只需提供一个页面的 ArrayObjectAdapter(mRowsAdapter) 对象,通过
setAdapter()
将数据设置进去,Leanback 会自动根据 ArrayObjectAdapter 里的数据以及和它关联的 Presenter 将界面显示出来。
既然我们跟 Leanback 打交道只有这么几点,那么切入点应该就在这些,毕竟我们对 Leanback 并不熟,那么只能从我们接触到的地方来着手。
那么,再来想想,既然是要实现卡位获得焦点和失去焦点时放大和缩小动画,那么肯定是需要监听 ItemView 的焦点变化,对吧?那我们通常是怎么做的,无外乎就是在 RecyclerView.Adapter 里的 onCreateViewHolder()
或 onBindViewHolder()
里监听 ItemView 的焦点变化吧。
既然方向有了,那么就是要寻找 Leanback Home 界面对应的 RecyclerView.Adapter 是由哪个类实现的吧。我们也知道了在 Leanback 中 Presenter 的作用就是类似于 RecyclerView.Adapter,那么我们就先到 Presenter 里看一下。
ListRowPresenter 继承自 RowPresenter 继承自 Presenter,那么我们通过 Android Studio 跳到 Presenter 里看看。
Presenter 是个抽象类,有三个抽象方法, onCreateViewHolder()、onBindViewHolder()、onUnbindViewHolder()
,跟 RecyclerView.Adapter 很像吧。根据我们之前的分析, ItemView 焦点的监听通常是在 onCreateViewHolder()
或 onBindViewHolder()
里实现的,那么我们就去它的实现类 ListRowPresenter 里看一看。
ListRowPresenter 里找不到这三个方法的实现,那么就是由它的父类 RowPresenter 实现了,我们继续通过 AS 跳到 RowPresenter 里看看。
onCreateViewHolder()
里的代码我们不用去理解,当然你有时间有能力也可以,但现在主要是想搞懂它的卡位缩放动画实现,所以我们只要看有没有跟焦点监听相关的代码即可。很显然,这里面并没有找到,里面调用了几个方法,有些方法一看就知道作用是创建某个对象的,你们也可以点进去看看,这里我们着重看一下 initializeRowViewHolder()
这个方法。
好像也没找到跟焦点监听的相关代码,但是左边有个标志,说明子类 ListRowPresenter 有复写这个方法,那么代码运行时实际上是调用的之类的方法,那么我们就点进去看看。
代码很多,截图也没截完,但是我们发现了一个关键,找到了一个看名字就觉得跟焦点有关的方法 FocusHighlightHelper.setupBrowseItemFocusHighlight()
,那么到底是不是呢?我们继续点击去看一下。
这个方法的介绍大意就是说设置每行的 ItemView 即卡位获得焦点时的行为,这不就是指卡位的缩放动画嘛,看来我们找到了。看代码,是调用了 ItemBridgeAdapter 的 setFocusHighlight()
方法,继续跟进看一下。
方法就只是设置了 mFocusHighlight 变量的值,而 ItemBridgeAdapter 是继承 RecyclerView.Adapter 的,看来卡位的焦点监听就是在这里实现了。看一下 onCreateViewHolder()
方法就知道是不是了。
presenterView 其实就是在 Presenter 里创建出来的 ItemView,所以这里其实就是对卡位设置焦点的变化监听,viewHolder.mFocusChangeListener 应该是 View.OnFocusChangeListener 的对象,我们看一下。
mFocusChangeListener 初始化通过实例化一个类对象赋值,那么这个类应该就是实现 View.OnFocusChangeListener 接口的,我们继续看一下。
这下清楚了吧,焦点发生变化时,会去调用 mFcousHightlight 的 onItemFocused()
方法。而 mFcousHightlight 是之前 FocusHighlightHelper.setupBrowseItemFocusHighlight()
里调用了 ItemBridgeAdapter 的 setFocusHighlight()
方法传进来的,我们再看看它传进来的是什么。
看一下 BrowseItemFocusHighlight 这个类做了什么。
所以,在 ItemBridgeAdapter 里注册了焦点变化监听,当焦点变化时,通知 mFcousHightlight 执行 onItemFocused()
方法,而 mFcousHightlight 是 BrowseItemFocusHighlight 类的实例,所以实际上是来执行上图里的逻辑。看代码也很容易明白,设置 ItemView 的选中状态,并且去运行一个焦点动画,那么卡位的缩放动画应该就是在这里实现了。继续看一下是不是。
该方法其实就是创建一个动画对象,如果该对象有缓存的话,那么就从缓存中取出,没有的话,就 new 一个,这种缓存的思想很值得学习。
该类就是实现了缩放的动画效果了,通过实现 TimeAnimator.TimeListener 接口来实现的属性动画,当然缩放动画也可以用其他方式实现,无非就是对 View 进行放大、缩小而已,这里就不具体去分析了,感兴趣的可以自己来这里看看 Google 是如何实现缩放动画的,后期有时间的话我可以再来分析一下这个类。
好了,到这里基本就分析完了,Leanback 库关于卡位的缩放动画的实现,从我们要从哪里着手开始阅读源码到找到焦点监听实现的相关代码到动画实现的代码整个过程基本就是这样。以后大家在想看源码的某个功能是如何实现时,可以参考这种思路来进行分析,一步步的去跟进,只找我们目标相关的代码,这样可以不至于被整个源码的复杂性混乱掉。
最后,我想再总结一下上面的过程。
总结
- 卡位缩放动画的实现在类 FocusHighlightHelper 的内部类 FocusAnimator 里实现。
- 缩放动画跟 ItemView 的绑定过程:
RowPresenter#onCreateViewHoler()
-> RowPresenter#initializeRowViewHolder()
-> ListRowPresenter#initializeRowViewHolder()
-> FocusHighlightHelper#setupBrowseItemFocusHighlight()
-> ItemBridgeAdapter#setFocusHighlight() - 简单点说就是,当每一行的 View 要创建时,会注册一个焦点监听器,该行里的 ItemView 焦点发生变化时会从 ItemViwe 的 Tag 里取出缩放动画对象,如果没有则 new 一个,然后应用缩放动画。
最近刚开通了公众号,想激励自己坚持写作下去,初期主要分享原创的Android或Android-Tv方面的小知识,感兴趣的可以点一波关注,谢谢支持~~
转载于:https://www.cnblogs.com/dasusu/p/7475419.html
AndroidTv Home界面实现原理(二)——Leanback 库的主页卡位缩放动画源码解析相关推荐
- SEAL全同态加密开源库(七) rns剩余数系统-源码解析
SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-14 前言 这是SEAL开源库代码分析报告第六篇,本篇将分析util文件夹中的rns.h和rns. ...
- Android开发知识(二十二)LayoutInflater装载xml布局过程的源码解析
文章目录 前言 LayoutInflater实例 LayoutInflater的装载过程 include 标签解析 merge 标签解析 attachToRoot参数解析 View创建过程 (1)判断 ...
- SEAL全同态加密开源库(八) rns源码解析(2)
SEAL全同态加密开源库(七) rns剩余数系统-源码解析 2021SC@SDUSC 2021-11-21 前言 这是SEAL开源库代码分析报告第七篇,本篇将继续分析util文件夹中的rns.h和rn ...
- PyCrypto密码学库源码解析(二)RSA参数生成
Python Crypto库源码解析(二) RSA参数生成 * 版权声明 * 引用请注明出处,转载请联系: h0.1c@foxmail.com 本文主要讲解pycrypto库中RSA参数生成的实现方法 ...
- TiKV 源码解析系列文章(二)raft-rs proposal 示例情景分析
作者:屈鹏 本文为 TiKV 源码解析系列的第二篇,按照计划首先将为大家介绍 TiKV 依赖的周边库 raft-rs .raft-rs 是 Raft 算法的 Rust 语言实现.Raft 是分布式领域 ...
- react相关代码库以及框架的源码解析
持续更新中react相关库源码浅析, react ts3 项目 ???对react相关代码库以及框架的源码进行了一定的分析 ?react16.6 View contents 源码实例分析:可见runl ...
- EventBus原理与源码解析
一.概述 EventBus是针对Android优化的发布-订阅事件总线,简化了Android组件间的通信.EventBus以其简单易懂.优雅.开销小等优点而备受欢迎. 关于EventBus的基本使用不 ...
- libev源码解析——定时器原理
本文将回答<libev源码解析--I/O模型>中抛出的两个问题.(转载请指明出于breaksoftware的csdn博客) 对于问题1:为什么backend_poll函数需要指定超时?我们 ...
- Simple Dynamic Strings(SDS)源码解析和使用说明二
在<Simple Dynamic Strings(SDS)源码解析和使用说明一>文中,我们分析了SDS库中数据的基本结构和创建.释放等方法.本文将介绍其一些其他方法及实现.(转载请指明出于 ...
最新文章
- python中的正则表达式
- RedHat已更改其开源许可规则
- (二)文档请求不同源之window.name跨域
- Java高并发编程(五):Java中的锁Lock
- 关于能否命令Scrum团队的对话
- UDP协议抓包分析 -- wireshark
- FastGithub让Github畅通无阻
- numpy+matplotlib绘制正弦曲线
- python办公自动化案例-Python实战:自动化办公:Python 自动整理 Excel 表格
- word打开老是配置进度_word怎么转pdf?两个值得学习的高效转换法
- python函数手册 chm_python中文手册chm
- html5在线加密,HTML技巧——加密网页
- 对数正态随机数c语言程序,对数正态随机数
- CRM客户细分的价值
- 【Python爬虫】下载b站视频。超详细。
- URIError: URI malformed
- php画网络拓扑图,jtopo js插件绘制网络拓扑图
- CSplitterWnd窗口分割之——动态静态嵌套分割(二)
- MSDTC Service的访问权限
- 计算机网络(一):计算机网络概念、功能、组成
热门文章
- bash: _upvars: `-a2‘: invalid number specifier bash: /dev/null: 权限不够 bas
- 【机器视觉】 halcon中图像获取
- 【Linux】一步一步学Linux——whatis命令(14)
- 职称不用计算机考试吗,中级职称计算机考试需要什么条件可不用考试
- 很多字段的数据要插入另一张表_一文看懂数据库设计之逻辑设计,值得收藏
- 最新最全vuepress零基础搭建(github搭建+新增插件)
- 王爽《汇编语言(第三版)》检测点11.1
- 每天一道LeetCode-----找到1,2,...,n这n个数所有的组合,每个组合有k个元素,且元素大小递增
- 如何跳出两层循环嵌套
- vscode could not establish connection to linux The VS Code Server failed to start