AndroidTv Home界面实现原理(一)——Leanback 库的使用

本文关键字:实现  界面  使用  数据  一行  理解  应该  原理  滑动 


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


效果图

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

AndroidTv Home界面实现原理(一)——Leanback 库的使用

AndroidTv Home界面实现原理(一)——Leanback 库的使用

AndroidTv Home界面实现原理(一)——Leanback 库的使用

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

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

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

分析

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

AndroidTv Home界面实现原理(一)——Leanback 库的使用

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

AndroidTv Home界面实现原理(一)——Leanback 库的使用

这个是内容区域即可左右滑动又可上下滑动的视频列表区域,主页最复杂的实现应该就是这个地方了。要我实现的话,思路就是 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 界面:

AndroidTv Home界面实现原理(一)——Leanback 库的使用

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

AndroidTv Home界面实现原理(一)——Leanback 库的使用

初始化 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 绑定,比如:

AndroidTv Home界面实现原理(一)——Leanback 库的使用

最后调用 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,上下滑动是由什么实现还没啃透。下一篇等啃得差不多了,再来梳理一下。



扩展:

Android之RelativeLayout(相对布局)

RelativeLayout 相对布局相对布局 RelativeLayout 允许子元素指定它们相对于其父元素或兄弟元素的位置,这是实际布局中最常用的布局方式之一。它灵活性大很多,当然属性也多,操作难度也大,属性之间产生冲突的的可能性也大,使用相对布局时要多做些测试。<?xml version="1.0" encoding="utf-8"?><!-- <LinearLayout xmlns:android="http://......

Android的IPC机制实现方式之Messenger

Messenger可以翻译成信使,通过它可以在不同进程间传递Message对象有了它就可以轻松实现进程间的数据传递了。Messenger使用的方法相对AIDL比较简单,它对AIDL做了一层封装是的我们不需要像采用AIDL那样去实现进程通信那么麻烦,可以看看他的源码有AIDL的迹象。public final class Messenger implements Parcelable { private final IMessenger mTarget; public Messenger......

Android Dialog使用、自定义带动画的Dialog使用

效果图普通Dialogprivate void showNormalDialog() { final AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this); builder.setIcon(R.mipmap.ic_launcher) .setTitle("普通Dialog") .setMessage("这是一个普通的D......

Android序列化Parcelable、Serializable

在Android中序列化实体类的方法有两种:一:Serializable优点:此方法特别简单,只需直接在实体类上声明Serializable接口缺点:效率没有Parcelable高二:Parcelable,优点:序列化及反序列号效率高   缺点:当数据将会被缓存进内存中的时候不建议这么做,容易导致数据丢失使用方法:先码上未被序列化的实体类public class Student { private String name; private int age; ......

Android逆向之旅---Native层的Hook神器Cydia Substrate使用详解

一、前言在之前已经介绍过了Android中一款hook神器Xposed,那个框架使用非常简单,方法也就那几个,其实最主要的是我们如何找到一个想要hook的应用的那个突破点。需要逆向分析app即可。不了解Xposed框架的同学可以查看:Android中hook神器Xposed使用详解;关于hook使用以及原理不多解释了。今天我们再来看另外一个hook神器Cydia Substrate,关于这个神器网上也已经介绍了,应该有的同学已经使用过了,因为最近在破解一个游戏,奈何想hook他的一个so中的一个......

Android中级篇之Fresco-加载图片基础[详细图解Fresco的使用

Fresco简单的使用—SimpleDraweeView百学须先立志—学前须知:在我们平时加载图片(不管是下载还是加载本地图片…..)的时候,我们经常会遇到这样一个需求,那就是当图片正在加载时应该呈现正在加载时的图像,当图片加载失败时应该呈现图片加载时的图像,当我们重新加载这张图片时,应该呈现重试时图像,直到这张图片加载完成。这些繁琐并且重复的如果得不到简化的话,那将是一个开发人员的噩梦,现在好了,我们用 Facebook 出品的一个强大的图片加载组件 Fresco......

Android-->EventBus 3.0新版使用说明(及其使用方法)

EventBus 在新版中取消了原来的使用方式 public void onEvent(MessageEvent event) { log(event.message); }123 public void onEventMainThread(MessageEvent event) { textField.setText(event.message); }123public void onEventBackgroundThread(MessageEve......

5分钟轻松解决Android数据库访问,Cursor类的基础使用

相比于MySql等数据库,SqLite有它自己的工具Cursor,一次获取一行数据(在数据库中,一行包含了一个主键约束的索引的全部内容)。使用游标来读数据库一般分两步:(就像在游标卡尺上读数)1.横向的获取列名所对应的位置(储存在Cursor中的位置),getColumnIndex方法2.通过得到的位置,getString(index) or getInt(index)3.也可以做循环输出 while (cursor.moveNex()t){ //move方法 返回一个布尔值,当到达最后一行时,......

Android实战技巧:深入解析AsyncTask

AsyncTask的介绍及基本使用方法关于AsyncTask的介绍和基本使用方法可以参考官方文档和Android实战技巧:多线程AsyncTask这里就不重复。AsyncTask引发的一个问题上周遇到了一个极其诡异的问题,一个小功能从网络上下载一个图片,然后放到ImageView中,是用AsyncTask来实现的,本身逻辑也很简单,仅是在doInBackground中用HTTP请求把图片的输入流取出,然后用BitmapFactory去解析,然后再把得到的Bitmap放到ImageView中。这个......

Android native service实例(一)

AOSP版本:android-7-0-0_r6项目结构:位于android-7-0-0_r6\frameworks\native\services\thinking_test下1、service:native service的主体,即服务的实现部分2、server:native service的载体,即启动和注册服务的部分。3、client:客户端程序,服务调用封装。4、test:测试client--------------------------------------------------......

Android上一个类似PathMenu效果的自定义View源码分析

出处: 炎之铠邮箱:yanzhikai_yjk@qq.com 博客地址:http://blog.csdn.net/totond 本文原创,转载请注明本出处! 本项目GitHub地址:https://github.com/totond/YMenuView 欢迎 Star or Fork! 效果总图: 前言  网上这种类似PathMenu的菜单很多,但是基本都不符合我项目的需求,想看他们的源码实现然后做出修改,进行二次开发来适应我的项目需求,但是发现——以我现在的能力,......

Android开源库:手把手教你实现一个简单好用的搜索框(含历史搜索记录)

前言Android开发中,类似下图的搜索功能非常常见今天,我将手把手教大家实现一款 封装了 历史搜索记录功能 & 样式 的Android 自定义搜索框 开源库,希望你们会喜欢。 已在Github开源:地址:SearchView,欢迎 Star !目录1. 简介一款封装了 历史搜索记录功能 & 样式 的Android自定义搜索框 已在Github开源:地址:SearchView,欢迎 Star !2. 需求场景在开始coding前, 理解好用户的需求场景 有助于我们更好地设计......

深入解析Android Design包——Behavior

上一篇深入解析AndroidDesign包——NestedScroll 已经说过了,在AndroidDesign包中主要有两个核心概念:一是NestedScroll,另一个就是Behavior。 相比于NestedScroll这个概念来说,Behavior分析起来会难很多,因为它几乎遍布了AndroidDesign包的每一个控件,种类繁多;另外Behavior提供了二十多个空方法给使用者来重写,主要分为四类: 1.与Touch事件相关的方法 2.与NestedScroll相关的方法 3.与控件依......

Android 逐帧动画:关于 逐帧动画 的使用都在这里了!

前言动画的使用 是 Android 开发中常用的知识可是动画的种类繁多、使用复杂,每当需要 采用自定义动画 实现 复杂的动画效果时,很多开发者就显得束手无策本文将详细介绍 Android 动画中 逐帧动画的原理 & 使用 关于Android 动画的系列文章:动画的使用,请参考文章: Android 属性动画:这是一篇很详细的 属性动画 总结&攻略 Android 动画:手把手教你使用 补间动画 Android 动画:你真的会使用插值器与估值器吗?(含详细实例教学)自定义View的......

Android中如何让TextView显示指定的行数并且多出的部分显示省略号

大家都知道,如果要让TextView只显示一行,多出部分用省略号代替的话非常容易,只需要为xml文件中的TextView控件添加android:singleLine="true"即可,那么如果我想让它显示多行的时候应该怎么做呢?其实也很简单,只要添加以下两个属性就可以了:android:lines="2"android:ellipsize="end"这样就可以让TextView最多显示2行,如果要显示指定的其它行数,只要修改上面的and......

Android打开某个activity时自动弹出输入法键盘

最近在做一个可以让用户修改自己账户资料的activity,具体是打开后有一个EditText,然后用户可以在这里输入相关信息,但是做好后发现,进入这个activity时系统并没有自动弹出输入法键盘,于是上网搜索,发现一个很简单的方法,就是在manifest清单文件对应的activity配置中加入一句android:windowSoftInputMode="stateVisible|adjustResize"就可以了:<!-- 修改用户资料 --><activ......

Android技术——视图切换(四)“ViewSwitcher+手势识别”实现视图的滑动切换

Android技术——视图切换(一)~(四)项目的源代码在:https://github.com/YongYuIT/MeiNv_Liulanqi上文《Android技术——视图切换(三)》实现的图片切换,虽然切换时有动画效果,但是却需要使用按钮才能切换。这个实例中,将尝试用手势识别代替按钮来实现图片切换。这个实例也是基于前三篇文章里的项目添加而来的。/MeiNv_Liulanqi/res/layout/activity_view_switcher_huadong.xml文件:<Relati......

Android利用ffmpeg产生推流

目标在安卓手机客户端有一个视频文件,利用ffmpeg产生推流。借助nginx-rtmp-module推送给另一客户端(简单起见用PC上的VLC)。VLC播放这个视频流。本次实验重点是第一步,即利用ffmpeg产生推流。1、获得ffmpeg库1/1 可以直接在ffmpeg官网下载源码,在Ubuntu下借助NDK编译得到.so库。关于这点,可以参照https://trac.ffmpeg.org/wiki/CompilationGuide/Android1/2 还可以借助github上的开源项目htt......

Android文件管理器开发对各类文件的打开以及处理

针对Android6.0开发的对读写权限的处理public class AppUtil { // Storage Permissions private static final int REQUEST_EXTERNAL_STORAGE = 1; private static String[] PERMISSIONS_STORAGE = { Manifest.permission.READ_EXTERNAL_STORAGE, Manifest.per......

android音频(二)——faad2编译和使用

参考http://blog.csdn.net/coloriy/article/details/52053144http://blog.csdn.net/jwzhangjie/article/details/8767077http://blog.csdn.net/yuan1125/article/details/50668412编译cd ~/Downloads/wget https://nchc.dl.sourceforge.net/project/faac/faad2-src/faad2-2.7......