本文来自网易云社区

作者:孙有军

开发的TV应用发现在部分电视上可以显示完整,而其他部分电视显示不全,周围都会遮挡了。

原因

这是因为部分老的电视有一个overscan的概览,什么叫overscan呐?官方解释如下:

During the evolution of TV technology, overscan originally described an area of TV content outside of a safe zone that most TVs could reliably display. Even on some of today’s HDTV flat screens, areas outside that zone may not be visible.

整个展示的界面是外面整个矩形框,而可见区域是内部的矩形框,因此如果你布局的内容紧邻边界,就会导致部分电视不能完整显示整个内容。

解决方案

上面的问题,我们怎么解决呐?这里给出两种解决方案。

设置调整

虽然老的电视有overscan的概念,内容显示不全,但是电视可以设置他的显示内容距离电视边框的距离,这里主要依靠人为的手动设置,方式如下:

一般都是选择遥控板的设置,进入设置界面,选择显示,边距调整

经过上述方式的调整,可以设置内容与边框有一定的距离,这样可以让所有的内容都显示出来。

难点:该方式必须要用户手动调整,如果不调整则显示内容被遮挡体验效果比较差

UI调整

既然让大家都采用手动调整是比较困难的,那有没有从应用层面来解决该问题的方法,有,肯定有,官方的文档也给出了解决方案:

Build a 5% margin into your TV screen designs to account for overscan area the TV may not display correctly. On a 1920 x 1080 screen, this margin should be a minimum of 27 pixels from the top and bottom edges and a minimum of 48 pixels from the right and left edges of the picture.

上面的意思是,在设计界面的时候,就空出四周的overscan距离,以1920*1080为例上下27px,左右48px,让显示的内容完全处于安全区域,周围都是无关内容区域。

缺点:如果设计的内容需要靠近边界,比如说底部有一个导航条,可以显示与影藏,这种时候就需要贴近边界进行设计。如果再设计的时候空出一部分,那在overscan的电视上展示较好,无overscan的电视展示就比较差,如果不空,这效果相反

自适应?

既然上面的两种方案都是有缺点的

全部让用户手动设置不显示

空出部分内容,在有的时候会显示效果比较差

那有没有一种方法来解决上面面临的问题?能够根据电视状况自动缩放内容,在有overscan的电视上,拿到overscan的值,设置显示内容与边界为overscan的值,在没有overscan的电视上保持内容不调整。

方案探索

首先我们看代码,看看代码中是否有overscan的值,经过一番查找,在Android中有一个Display类,他包含了很多显示信息,其中有一个字段为DisplayInfo,DisplayInfo包含了其他的一些显示信息。其中有四个字段如下:

/**

* Describes the characteristics of a particular logical display.

* @hide

*/

public final class DisplayInfo implements Parcelable {

....

/**

* @hide

* Number of overscan pixels on the left side of the display.

*/

public int overscanLeft;

/**

* @hide

* Number of overscan pixels on the top side of the display.

*/

public int overscanTop;

/**

* @hide

* Number of overscan pixels on the right side of the display.

*/

public int overscanRight;

/**

* @hide

* Number of overscan pixels on the bottom side of the display.

*/

public int overscanBottom;

public DisplayInfo(){

}

....

}

这里我们省略了其他的代码,可以看到包含有overscanLeft, overscanTop,overscanRight,overscanBottom,这就是Overscan的值,到这里感觉有希望。既然有这四个值,那我们获取到这四个值再设置会界面应该就能达到我们想要的效果。

读取overscan

从上面的代码中我们可以看到DisplayInfo是被hide掉的,四个值也是被hide掉的,说明从正常的先拿到Display,再拿到DisplayInfo,之后再获取四个值是不行的了,那我们反射来获取该值,代码如下:

public static Rect getOverScan(){

if (overScan == null) {

overScan = new Rect();

try {

WindowManager manager = (WindowManager) AppProfile.getContext().getSystemService(Context

.WINDOW_SERVICE);

Display display = manager.getDefaultDisplay();

Class clazz = Display.class;

Field mDisplayInfo = clazz.getDeclaredField("mDisplayInfo");

mDisplayInfo.setAccessible(true);

Object displayInfo = mDisplayInfo.get(display);

Class displayInfoClazz = Class.forName("android.view.DisplayInfo");

Field overscanLeft = displayInfoClazz.getDeclaredField("overscanLeft");

overScan.left = overscanLeft.getInt(displayInfo);

Field overscanTop = displayInfoClazz.getDeclaredField("overscanTop");

overScan.top = overscanTop.getInt(displayInfo);

Field overscanRight = displayInfoClazz.getDeclaredField("overscanRight");

overScan.right = overscanRight.getInt(displayInfo);

Field overscanBottom = displayInfoClazz.getDeclaredField("overscanBottom");

overScan.bottom = overscanBottom.getInt(displayInfo);

} catch (Exception e) {

}

}

return overScan;

}

首先获取到Display,之后在反射获取DisplayInfo,最后在读取四个值。

也可以直接反射获取Display下的getOverscanInsets函数, getOverscanInsets函数如下:

/**

* @hide

* Return a rectangle defining the insets of the overscan region of the display.

* Each field of the rectangle is the number of pixels the overscan area extends

* into the display on that side.

*/

public void getOverscanInsets(Rect outRect){

synchronized (this) {

updateDisplayInfoLocked();

outRect.set(mDisplayInfo.overscanLeft, mDisplayInfo.overscanTop,

mDisplayInfo.overscanRight, mDisplayInfo.overscanBottom);

}

}

反射获取方式如下:

public static Rect getOverScan1(){

Rect overScan = new Rect();

try {

WindowManager manager = (WindowManager) AppProfile.getContext().getSystemService(Context.WINDOW_SERVICE);

Display display = manager.getDefaultDisplay();

Class clazz = Display.class;

Method getOverscanInsets = clazz.getMethod("getOverscanInsets", Rect.class);

getOverscanInsets.invoke(display, overScan);

LogUtil.free(overScan.toString());

} catch (Exception e) {

}

return overScan;

}

我们采用上面方法在debug状态下读取了一下DisplayInfo的内容:

Display id0: DisplayInfo{"内置屏幕", app1280 x720, real1280 x720, largest app1280 x1255, smallest app720 x695,50.0 fps, rotation0, density160 (160.0 x160.0) dpi, layerStack0, type BUILT_IN, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=1.0, width=1280, height=720, scaledDensity=1.0, xdpi=160.0, ydpi=160.0}, isValid=true

反射后获取,发现并没有overscan的值,很遗憾四个值都是0。可是我测试的电视是有overscan的。代码写错了?

我采用命令来设置overscan的内容:

adb shell wm overscan 10,20,30,40

分别设置overscan的值为10, 20, 30, 40,之后我再一次获取DisplayInfo的值,内容如下:

Display id0: DisplayInfo{"内置屏幕", app1280 x720, real1280 x720, overscan (10,20,30,40), largest app1280 x1255, smallest app720 x695,50.0 fps, rotation0, density160 (160.0 x160.0) dpi, layerStack0, type BUILT_IN, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS}, DisplayMetrics{density=1.0, width=1280, height=720, scaledDensity=1.0, xdpi=160.0, ydpi=160.0}, isValid=true

这里可以看到明确有overscan的内容,并且就是我们命令设置的值,这就尴尬了,系统默认值获取不到,手动设置可以获取。希望之路破灭。

总结

如果有人实现了自适应的方式,麻烦请告知一下。目前只能采取UI界面调整的方式来避免该问题。

网易云免费体验馆,0成本体验20+款云产品!

更多网易研发、产品、运营经验分享请访问网易云社区

android+tv+社区,Android TV Overscan相关推荐

  1. 一起看 I/O | Google TV 和 Android TV OS 的最新进展

    在接触到的娱乐内容与日俱增的今天,有研究表明,三分之一的美国家庭现每周的电视观看时长在 25 个小时以上.随着电视体验的不断演进,我们也为自己设定了一个目标,那就是为用户打造量身定做的电视使用体验,让 ...

  2. air.tv.douyu.android,斗鱼(air.tv.douyu.android) - 7.0.6.1 - 应用 - 酷安

    权限信息 · 控制近距离通信 · 检索正在运行的应用 · 修改系统设置 · 关闭其他应用 · 在其他应用之上显示内容 · 拍摄照片和视频 · 录音 · android.permission.CAPTU ...

  3. 基于Android Tv制作一个Tv桌面(二)

    标题基于Android Tv制作一个Tv桌面(二) 这里是获取APP的各种信息,不知道为什么这一步只能在主类MainActivity 上进行,不能在其他的类进行此操作,也许是我见识短浅的原因吧,因为其 ...

  4. 团队环境搭建:MTK平台,Android 9.0内销TV编译服务器配置

    团队环境搭建:MTK平台,Android 9.0内销TV编译环境配置 文章目录 团队环境搭建:MTK平台,Android 9.0内销TV编译环境配置 一.前言 二.硬件环境要求 四 .替国内换源:so ...

  5. 【Android TV】Android 8.0下 ,TV系统通知音失效

    问题描述: Android 8.0的TV系统通知音失效 分析过程: 跟踪触发通知的流程, SystemUI 通知音播放是调用Ringtoneplayer播放类的,这个接收的参数是声音的URI路径,是从 ...

  6. u盘里android文件夹作用,Android应用开发android tv box ---- 插入u盘直接播放指定文件夹中的视频...

    本文将带你了解Android应用开发android tv box ---- 插入u盘直接播放指定文件夹中的视频,希望本文对大家学Android有所帮助. android tv box ---- 插入u ...

  7. android tv gridview,Android TV开发经验总结---控件Gridview使用

    前Android TV 开发的资料不是蛮多,经过一系列的搜索,目前比较适用的框架推荐 冰雪情缘TV / Android-TV-Frame    项目地址:https://git.oschina.net ...

  8. android tv 帮助,android TV端各类焦点问题

    1. android:focusable与android:focusableInTouchMode 前者针对在键盘下操作的情况,如果设置为true,则键盘上下左右选中,焦点会随之移动. 而后者,显然是 ...

  9. android xml 焦点,android TV 焦点选中放大效果

    使用github开源项目(非常感谢作者): 这里是项目地址:https://github.com/evilbinary/TvWidget 1.个人只需要RelativeLayout 布局,所以只是用了 ...

最新文章

  1. HDU - 4738 Caocao's Bridges(边双缩点)
  2. 如果用超级计算机渲染阿丽塔,【集群渲染】《阿凡达》幕后的渲染集群与渲染技术...
  3. 大数据_Flink_数据处理_运行时架构4_作业调度原理及思考问题---Flink工作笔记0019
  4. C++基础之返回数组
  5. Xocde一次版本升级遇到的问题 (Code Sign Error)
  6. css之div兼容性问题
  7. Gradle 插件Debug调试
  8. java 状态常量_Java 变量和常量
  9. python爬虫刷网课答题_python实践:利用爬虫刷网课
  10. 压缩base64图片大小
  11. ppt 计算机课件模板,大学计算机基础课件模板.PPT
  12. 这10个超厉害的工具堪称神器,却很少人知道!
  13. “笨办法”学Python3——练习5 更多变量和打印
  14. uniapp 上传图片到华为云obs
  15. 全国所有城市人均GDP排名(包含县级市)
  16. teradata数据库分析函数_TERADATA中函数的使用
  17. windows7系统能安MATLAB几,matlab7.0安装win7系统详细使用方法
  18. ccnp需要什么学历_CCNP的完整形式是什么?
  19. 老K白话| 密集存储系统演化史(文尾投票)
  20. 智慧园区/楼宇解决方案

热门文章

  1. 知名企业面试、笔试题
  2. JDK9-17开发常用的新特性
  3. DD-WRT 客户端模式设置 暨添加无线连接功能
  4. 千兆以太网TCP协议的FPGA实现。
  5. Adobe年底推出Creative Suite 3?
  6. 小程序反编译-获取源码
  7. Unity Shader - 羽化效果
  8. 1.已知长方形的长和宽,求长方形的周长和面积。
  9. SkeyeVSS安防视频云解决方案助力解决幼儿园安全系统防护问题
  10. jenkins如何得到日期