3、TV应用基础结构:Leanback库介绍、Activity与Fragment在TV中的使用

好,咱们今天聊聊TV应用的基础骨架。说白了,就是搞清楚Leanback库是干嘛的,以及Activity和Fragment在电视上该怎么用。

我刚开始做TV开发时,也踩过不少坑。手机上的那套写法,搬到电视上,很多地方行不通。为什么?因为交互方式完全不同。手机靠触摸,电视靠遥控器。你想想看,一个没有触摸屏的设备,你总不能用手指去戳屏幕吧?

所以,Google专门搞了个Leanback库。它就是为电视而生的。

3.1 Leanback库:TV开发的基石

Leanback库,说白了就是一套专门给电视用的UI组件和工具集。它帮你处理了焦点移动、按键导航、大屏布局这些头疼的问题。

我个人习惯,每次新建TV项目,第一件事就是引入Leanback依赖。别嫌麻烦,它真的能省很多事。

核心依赖:

implementation 'androidx.leanback:leanback:1.0.0'

Leanback库提供了几个关键的东西:

  • BrowseFragment:浏览页面的核心,帮你搭建分类和内容列表
  • DetailsFragment:详情页面的基础框架
  • PlaybackFragment:播放器相关的UI组件
  • 各种Presenter:负责把数据渲染成界面上的卡片

我记得有一次,团队里新来的同事想自己写焦点管理,折腾了两天,各种bug。后来我让他直接用Leanback的BrowseFragment,半天就搞定了。嗯,这里要注意,不要重复造轮子。

3.2 Activity在TV中的特殊之处

TV上的Activity,和手机上的Activity,本质上是一样的。但有几个关键点,你得注意。

第一,主题必须用NoActionBar。

电视上不需要ActionBar,那玩意儿占地方,而且遥控器操作起来也不方便。

<activity
    android:name=".MainActivity"
    android:theme="@style/Theme.Leanback">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LEANBACK_LAUNCHER" />
    </intent-filter>
</activity>

看到那个 category.LEANBACK_LAUNCHER 了吗?这是TV应用特有的。没有它,你的应用在电视上可能无法被识别为可启动的应用。

第二,屏幕方向固定为横屏。

电视永远是横屏的。别想着搞竖屏,那在电视上就是个灾难。

android:screenOrientation="landscape"

我曾经见过一个应用,没设置横屏,结果在电视上显示得歪歪扭扭。用户遥控器按了半天,焦点都不知道跑哪去了。

3.3 Fragment:TV界面的主力军

在TV开发中,Fragment的使用频率远高于Activity。为什么?因为电视屏幕大,内容多,用Fragment做模块化拆分,管理起来更清晰。

Leanback库里的核心Fragment,我列一下:

Fragment 用途 我常用的场景
BrowseFragment 主界面浏览,分类+内容列表 首页、频道列表
DetailsFragment 展示某个内容的详细信息 电影详情、商品详情
PlaybackFragment 视频播放控制界面 播放器UI
SearchFragment 搜索功能 全局搜索

拿BrowseFragment举个例子。你想想看,电视上的首页,左边是分类列表,右边是内容卡片。这个布局,用BrowseFragment实现起来非常方便。

public class MainFragment extends BrowseFragment {
    @Override
    public void onActivityCreated(Bundle savedInstanceState) {
        super.onActivityCreated(savedInstanceState);
        
        // 设置标题
        setTitle("我的TV应用");
        
        // 设置UI风格
        setHeadersState(HEADERS_ENABLED);
        setBrandColor(getResources().getColor(R.color.primary));
        
        // 加载数据
        loadRows();
    }
    
    private void loadRows() {
        // 这里用ArrayObjectAdapter添加数据行
        ArrayObjectAdapter rowsAdapter = new ArrayObjectAdapter(new ListRowPresenter());
        // ... 添加具体数据
        setAdapter(rowsAdapter);
    }
}

你看,代码量并不多。Leanback帮你处理了焦点移动、按键事件、布局适配。你只需要关心数据怎么来,卡片长什么样。

小技巧: 在BrowseFragment中,如果你想让分类标题一直显示,可以调用 setHeadersState(HEADERS_ENABLED)。如果想让标题自动隐藏,用 HEADERS_DISABLED。我个人习惯在内容较多的页面让标题常驻,方便用户快速切换分类。

3.4 焦点管理:TV交互的灵魂

电视上没有触摸,全靠遥控器上的方向键和确认键。所以,焦点管理是TV开发的重中之重。

Leanback库的组件,默认就支持焦点移动。但如果你用了自定义View,就得手动处理了。

我曾经在一个项目中,用了自定义的卡片布局,结果焦点移动不按套路走。用户按右键,焦点跳到下面去了。排查了半天,发现是布局里某个View的 android:nextFocusRight 属性没设置对。

避坑指南: 自定义View时,一定要显式指定焦点移动方向。用 android:nextFocusDownandroid:nextFocusUpandroid:nextFocusLeftandroid:nextFocusRight 这四个属性。别指望系统能自动猜对你的意图。

<Button
    android:id="@+id/btn_play"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:text="播放"
    android:nextFocusRight="@id/btn_add_favorite"
    android:nextFocusLeft="@id/btn_back" />

另外,焦点选中后的视觉效果也很重要。Leanback提供了 FocusHighlightHandler,你可以自定义焦点放大、颜色变化等效果。

3.5 知识体系总览

为了让你更直观地理解TV应用的基础结构,我画了一张图。它把Leanback库、Activity、Fragment以及焦点管理的关系串起来了。

TV应用基础结构知识体系 TV Activity Leanback Fragment 家族 BrowseFragment DetailsFragment PlaybackFragment SearchFragment Leanback 库核心能力 焦点管理 | 按键导航 | 大屏布局 | Presenter渲染 焦点管理:nextFocusDirection 自定义View必须显式指定方向

这张图把整个结构理清楚了。从上到下,Activity承载Fragment,Fragment依赖Leanback库,Leanback库帮你搞定焦点和导航。你只要按这个路子走,基本不会出大问题。

3.6 实战中的一些建议

最后,分享几个我在实战中总结的点:

  • 别在TV上用DialogFragment:电视上的弹窗体验很差,尽量用内嵌的Fragment或者Overlay代替。
  • Fragment的切换用FragmentTransaction:记得加上 addToBackStack(null),方便用户按返回键回退。
  • 数据加载用异步:电视的硬件性能参差不齐,别在主线程做耗时操作。我用过一些低端盒子,稍微卡一下,用户就以为死机了。

核心总结: TV应用的基础结构,就是Activity + Leanback Fragment + 焦点管理。把这三块搞明白,你的TV应用就站稳了脚跟。

好了,这一章的内容就到这里。记住,电视开发没那么神秘,关键是理解它的交互逻辑。Leanback库已经帮你铺好了路,你只需要沿着它走就行。


公众号:蓝海资料掘金营,微信deep3321