接下去应该是梳理一下 Android Tv 主界面实现原理及解析的一个系列博客了,大体上的安排是先介绍 Google 官方提供的 Leanback 库的使用,如何使用该库来实现简单的 Home 界面,然后再去分析 Leanback 主界面实现的相关源码,了解完 Google 是如何实现之后就可以扔掉 Leanback 自己来尝试实现,毕竟 Leanback 的可定制不高。


效果图

首先贴几张常见的 Home 界面效果:

第一张是爱奇艺 Tv 应用的 Home 界面,第二张是一个开源 Demo 的 Home 界面,第三张是 Google 官方 Tv Sample 的 Home 界面

比较常见的 Home 界面风格应该是第一张和第二张的形式,这两种的 ui 实现也不一样,因此我就想搞懂这两种界面分别是如何实现的!!

目前重点研究第一张的实现方式吧,毕竟 Google 的 Leanback 库实现出来的效果跟第一张有一些共同点,因此可以从 Leanback 入手来学习它是如何实现的。而至于第二张的实现原理,目前还没有思路,也暂时找不到相关资料来学习,Github 上面的 demo 都是忽悠人,控件全都是在 xml 中直接写死的,所以第二张图的 Home 界面实现原理以后再慢慢研究吧,或者有读者可以指点一二,非常感激。

分析

先大概的来分析一下第一张爱奇艺 Home 界面的实现:

这个是 Tab 标签栏,选中不同的 Tab,内容区会显示不同的视频列表,这里的实现应该是 TabLayout + Fragment 的形式,或者 TabLayout + ViewPager,但 ViewPager 在 Tv 上使用好像会出很多坑。

这个是内容区域即可左右滑动又可上下滑动的视频列表区域,主页最复杂的实现应该就是这个地方了。要我实现的话,思路就是 RecyclerView 嵌套 RecyclerView 来实现,先不谈 RecyclerView 这种滑动的控件在 Tv 上会出问题,嵌套这个坑就足够你填的了。

在 Tv 上,可以用 HorizontalGridView 和 VerticalGridView 替代 RecyclerView 使用。但要实现左右单行滑动,上下整体滑动的效果,我只能想到上下用 VerticalGridView 来实现,每一行是它 itemView,而每一行的实现则用 HorizontalGridView 来实现。也就是 1 个 VerticalGridView + 多个 HorizontalGridView 来实现。

但这样的嵌套仍会有许多问题出现,比如快速移动时的焦点丢失、性能问题、每一行的 View 如何缓存、复用等。

有大佬清楚解决方案,或者有其他实现思路的小伙伴们欢迎指点一下,实在没有,那就只能自己慢慢去啃 Leanback 的相关源码,然后再来梳理一下了。

使用

不出意外,接下去的空闲时间应该就是啃 Leanback Home 界面实现的相关源码,在此之前,先了解一下 Leanback 如何使用,哪些类是重点,后面分析时才方便入手。

以下是我觉得应该理解的类:

  • BrowerFragment:用来展示可左右上下滑动的视频列表界面
  • ArrayObjectAdapter:作用类似于 List,可以用于装每一行的数据,也可以用于装一行里的每一个 item 数据
  • ListRowPresenter:Leanback 库中的 Presenter 作用都有些类似于 RecyclerView.Adapter
  • ListRow:可以理解成一个 Mode,也就是把每一行抽象封装成一个 ListRow

用法跟 RecyclerView 很像,就是可能单独从命名上来理解会有些乱。只要你自己尝试去利用 Leanback 去实现个最简单的 Home 界面,大体就能理解了。比如,要实现下面这个 Home 界面:

首先,界面显示的数据都存在 ArrayObjectAdapter 里面,在 RecyclerView 时我们是存在 ArrayList 里:

初始化 ArrayObjectAdapter 对象时需传入一个 Presenter 进去,这里跟 RecyclerView 的使用有些不同,在 RecyclerView 里,我们是将 List 对象传给 Adapter,让 Adapter 去将数据和 itemView 绑定。这里虽然反过来将 Adapter(Presenter) 传入 List(ArrayObjectAdapter) 里,但其实作用也差不多,也是将两者关联起来。只是多了一个步骤,通过一个桥梁类 ItemBridgeAdapter 来将 ArrayObjectAdapter 里的数据传给 Presenter 。之后 Presenter 的工作就跟 RecyclerView.Adapter 一样了。

前面说了 Presenter 作用类似于 Adapter,它是个抽象类,继承它的之类需要实现三个方法:onCreateViewHolder()、onBindViewHolder()、onUnbindViewHolder(),同 RecyclerView.Adapter 一样,在 onCreateViewHolder() 里面创建 itemView,然后在 onBindViewHolder() 里面将数据和 itemView 绑定,比如:

最后调用 BrowerFragment 的 setAdapter() 将总的 ArrayObjectAdapter 对象设置进去,就可以了。使用很简单,如果你第一次接触,然后直接来看这篇,也许看不懂,建议你去看看这篇博客,或者自己去看一下 Google 官方的 Tv demo,然后再回来看,相信你理解就会跟深刻了。

思考

  1. 学会初步使用 Leanback 实现一个简单的 Home 界面后,你会发现,我们只需要提供每一行的数据,以及每行自己 itemView 的布局和数据绑定方式即可。但这完全没有涉及到 HorizontalGridView 和 VerticalGridView ,那么它内部的实现原理又是什么呢?

  2. 如果你运行了 Google 官方 Tv sample 或者自己利用 Leanback 实现了简单的 Home 界面的话,你会发现,我们焦点在某个 item 上时,这个 item 会放大,焦点离开又恢复正常,这个 Leacback 又是怎么实现的呢?

  3. 如果你运行了爱奇艺的 Tv 应用,你会发现,它焦点在移动到边界时 item 会有抖动的效果,这又要如何实现呢?

本系列梳理博客大概就是要理清上面的问题,后两个比较简单,看了 Leanback 的源码,已基本明白。所以难啃的点还是在于 Home 界面的 ui 实现原理,目前只能大体上明白每一行是一个 HorizontalGridView,上下滑动是由什么实现还没啃透。下一篇等啃得差不多了,再来梳理一下。

AndroidTv Home界面实现原理(一)——Leanback 库的使用的更多相关文章

  1. AndroidTv Home界面实现原理(二)——Leanback 库的主页卡位缩放动画源码解析

    先看个效果图: 上一篇中,我们留了问题,在 Tv Home 界面这种很常见聚焦卡位放大动画效果,我们这一篇就来看看 Leanback 库是怎么实现的. 如果要我们自己实现的话,思路应该不难,就是写个放 ...

  2. 使用AsyncTask异步更新UI界面及原理分析

    概述: AsyncTask是在Android SDK 1.5之后推出的一个方便编写后台线程与UI线程交互的辅助类.AsyncTask的内部实现是一个线程池,所有提交的异步任务都会在这个线程池中的工作线 ...

  3. CodeFirst写界面——自己写客户端UI库

    何谓CBS程序 CBS程序就是Client+Browser+Service的程序 纯CS程序写界面,有各种难处,那么我就在Client端引入Browser,让Browser渲染基于HTML的UI界面 ...

  4. QT新建空白项目-添加QT设计师界面类时出现的各种库无法导入识别

    按照教材上先新建一个空的项目--添加Qt设计师界面类时 出现各种 库无法识别 解决方法: 在 .pro文件中加入一行 QT += widgets 去构建中先执行 qmake 然后再构建一下  ok了 ...

  5. xtrabackup原理,整库,单表,部分备份恢复

    物理备份xtrabackup原理 Percona XtraBackup(简称PXB)是 Percona 公司开发的一个用于 MySQL 数据库物理热备的备份工具,支持 MySQl(Oracle).Pe ...

  6. 55.Qt-将界面程序封装成静态库

    1.生成dll 然后选择创建静态链接库: 创建的时候,记得勾选QtGui,并且修改pro文件,添加下面1句(这样就可以创建界面了): 修改staticlib.cpp: #include "s ...

  7. 54.Qt-将界面程序封装成动态库DLL

    1.生成dll 然后选择创建共享库: 创建好后,修改pro文件,改为下面两句(这样就可以创建界面了):  然后修改sharedlib.h: #ifndef SHAREDLIB_H #define SH ...

  8. 【情人节选帽子】TCS34725颜色传感器和Python图形界面编程(STM32 HAL库)

    截图 描述: l  STM32 HAL库编程 l  使用模拟IIC通信,方便程序移植 l  Python界面编写,蘑菇头的帽子是什么颜色 l  STM32 HAL库串口通信 l  Python界面使用 ...

  9. ThinkPHP内置标签库原理(Cx标签库)

    任何一个模板引擎的功能都不可能是为你量身定制的,具有一个良好的可扩展 机制也是模板引擎的另外一个考量,Smarty采用的是插件方法来实现扩展,ThinkTemplate由于采用了标签库技术,比Smar ...

随机推荐

  1. Django--Uploaded Files以及Handlers

    一.表示已经上传的文件(uploaded files)的类 表示已经上传的文件的类有下面几个: class UploadedFile 在文件上传的期间,实际的文件数据被存储在request.FILES ...

  2. Ambari安装之部署本地库(镜像服务器)(二)

    部署本地库(镜像服务器) (1)下载HortWorks官网上的3个库到本地(也可以在线下载,但是速度会很慢) 我们先把hortworks官网上需要下载的3个库下载到本地(这个还是需要很长时间的,当然你 ...

  3. JavaScript中的设计模式:状态模式

    前几天写了一个贪吃蛇小游戏,正好用到了状态模式. 定义 当一个对象内部状态发生改变时候,会导致其行为的改变,这看起来像是改变了对象. 简单的例子 如果一个函数要更具某一个对象的状态来判断该对象应该执行 ...

  4. TensorFlow conv2d原理及实践

    tf.nn.conv2d(input, filter, strides, padding, use_cudnn_on_gpu=None, data_format=None, name=None) 官方 ...

  5. (转)示例化讲解RIP路由更新机制

      目录(?)[+]   以下内容摘自最新上市的“四大金刚”图书之一<Cisco路由器配置与管理完全手册>(第二版)(其它三本分别为<Cisco交换机配置与管理完全手册>(第二 ...

  6. C++引用形参,函数返回多个值

    之前编代码有遇到过想让一个函数返回多个值的情况,low low的我不知道有什么办法,直接使用的全局变量将函数里的值传出去. 今天看书,<C++primer>第五版中文版第189页:使用引用 ...

  7. Java内存区域与对象创建过程

    一.java内存区域 Java虚拟机在执行Java程序的过程中会把它所管理的内存划分为若干个不同的数据区域.这些区域都有各自的用途,以及创建和销毁的时间,有的区域随着虚拟机进程的启动而存在,有的区域则 ...

  8. JVM学习笔记二:垃圾收集算法

    垃圾回收要解决的问题: 哪些内存需要回收? 线程私有区域不需要回收,如PC.Stack.Native Stack:Java 堆和方法区需要 什么时候回收? 以后的文章解答 如何回收? 首先进行对象存活 ...

  9. 如何免费使用jrebel 和eclipse 项目配合完成热部署功能

    天,感谢王同学分享了热部署插件,jrebel,说修改后台代码可以不用重启tomcat,于是立即下载使用....本来很简单的一个事情,因为参照了网上各种帖子,结果坑的不行....所以把自己的经验分享一下 ...

  10. Redis架构设计--客户端请求RedisServer时,server端持久化的部分操作