遥控器焦点乱跑?my-tv 的 5 个布局决策
【免费下载链接】my-tv我的电视 电视直播软件,安装即可使用项目地址: https://gitcode.com/GitHub_Trending/my/my-tv
用户按了三次方向键,焦点从频道列表跳到了右上角的"帮助"按钮上。TV 应用 UI 设计的核心就是这件事:屏幕大、遥控器键少,焦点自己走,必然走到用户没预期的地方。my-tv 是个装完就能看的电视直播应用,它的第一步是把焦点的活动范围收窄。
主界面只是一个空壳
activity_main.xml 里只有一个根 FrameLayout,没有子节点,还标了tools:deviceIds="tv":
<FrameLayout android:id="@+id/main_browse_fragment" tools:deviceIds="tv" />真正的界面是运行时由 Leanback 的 BrowseSupportFragment 注进来的,布局文件只声明"这页只给电视用"。Leanback 的 BrowseFragment 配置其实就一行,MainFragment.kt 的 onCreate 第一句:
headersState = HEADERS_DISABLED // 不显示头部和搜索栏数据来自 TVList.kt 里的一个 map,央视、地方、港澳台、国际 4 组,每组一行 ListRow,卡片上放频道 logo 加正在播出的节目名。好处是焦点只能在 4 行卡片之间动,按不到屏幕边缘,用户怎么按都不会迷路。
遥控器就几个键,导航必须可预测
能参与导航的按键其实就 5 个:上下切频道、中间确认、返回、帮助。所以焦点路径必须可预测。CardPresenter.kt 里的写法最直白:
cardView.isFocusable = true cardView.isFocusableInTouchMode = true卡片 300x101 像素,白底,logo 居中。高亮色#0096a6定义在 colors.xml 里,但翻代码会发现对应的 setOnFocusChangeListener 是被注释掉的——本来想聚焦时把信息区背景换成高亮色,后来放弃了,高亮完全交给 Leanback 默认的缩放和边框。我的体感是这更稳:框架的聚焦动画统一,自己画反而容易和各系统版本打架。
导航路径则完全靠 ListRowPresenter 的默认算法:这 5 个 Android TV 布局文件里没有一处 nextFocusRight。行式结构下这够用——左右在行内走,上下切行,路径由行数决定。换成二维网格就不能指望默认值了,得手写路径。
网格改行式:频道列表样式的一次退让
频道列表不是一直长这样的。翻 HISTORY.md,v1.6.2 加了新的列表样式,v1.7.2 支持网格/行式切换,但注了条"软件重启后生效"。到 v2.0.0 一次修了两个 bug:"网格样式时点击空白处不退出"和"频道列表样式切换可能不生效"。
这是典型的取舍。网格一屏放得下更多频道,好看;但焦点变二维,遥控器没有滚动指示器,用户不知道右边还有没有频道,按着按着就丢了。行式焦点简单,配合菜单 3 秒自动关闭(v1.3.4 引入),把"停留在列表里"的时间也限制了。项目最后把网格留在设置里当选项,默认体验走行式。样式不做热切换、要重启生效,是妥协:比起切换瞬间维护两份焦点状态,重启更不容易出 v2.0.0 那种"切换不生效"的 bug。
间距用 dp 算,不用"合适"
定了行式,下一个问题是三米外看不看得清。频道号层 channel.xml 是个 90dp x 60dp 的盒子,40sp 粗体白字,marginEnd 170dp钉在右上;时钟层 32sp,marginEnd 50dp。两层同在右上角但不打架,就是靠这两个错开的偏移量。节目信息条 320dp x 80dp,距底边 20dp,标题 22sp 用#FFEEEEEE,节目名 16sp 用#B3EEEEEE——两行字靠透明度差 70% 分主次,这在电视上比换颜色可靠。设置弹层只有 300dp 宽,不铺满屏,4 个 Switch 竖排,遥控器按一下挪一格,按不到边界。
播放器页故意没有系统控制条
播放时所有浮层收起,剩下最"空"的文件 player.xml,全文不到 30 行:SurfaceView 和 media3 的 PlayerView 叠在黑色背景里,两个都写了:
<androidx.media3.ui.PlayerView app:use_controller="false" />系统控制条关掉,控制层自己画——频道号、时钟、信息条全叠在视频上。原因不复杂:系统控制条的焦点体系不知道你的应用状态,用户播放中误按方向键,焦点会飞出视频区钻进控制条。关掉之后,播放器页焦点只剩频道列表浮层和空白处,方向键按错了也不出界。
打开 channel.xml,把 marginEnd 从 170dp 改成 120dp,看看频道号贴到右边之后还留没留得下时钟。
【免费下载链接】my-tv我的电视 电视直播软件,安装即可使用项目地址: https://gitcode.com/GitHub_Trending/my/my-tv
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考