Android TV Overscan
本文来自网易云社区
作者:孙有军
开发的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 id 0: DisplayInfo{"内置屏幕", app 1280 x 720, real 1280 x 720, largest app 1280 x 1255, smallest app 720 x 695, 50.0 fps, rotation0, density 160 (160.0 x 160.0) dpi, layerStack 0, 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 id 0: DisplayInfo{"内置屏幕", app 1280 x 720, real 1280 x 720, overscan (10,20,30,40), largest app 1280 x 1255, smallest app 720 x 695, 50.0 fps, rotation0, density 160 (160.0 x 160.0) dpi, layerStack 0, 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 Overscan的更多相关文章
- 联发科发布全球首款搭载Android TV的智能电视系统芯片MT5595
联发科发布全球首款搭载Android TV的智能电视系统芯片MT5595 admin 资讯 01-07 1 1月7日消息,联发科宣布与Google共同开发出全世界第一个搭载Android TV操作系统 ...
- Android Tv 中的按键事件 KeyEvent 分发处理流程
这次打算来梳理一下 Android Tv 中的按键点击事件 KeyEvent 的分发处理流程.一谈到点击事件机制,网上资料已经非常齐全了,像什么分发.拦截.处理三大流程啊:或者 dispatchTou ...
- Android TV 电视调试和遥控器事件监听
Android TV 真机调试 要进行Android TV开发免不了要进行真机调试. 1.确定电视盒子和开发机器在同一局域网中 2.打开电视盒子的adb允许调试开关 3.进入adb所在文件夹进行adb ...
- Android TV开发总结(六)构建一个TV app的直播节目实例
请尊重分享成果,转载请注明出处:http://blog.csdn.net/hejjunlin/article/details/52966319 近年来,Android TV的迅速发展,传统的有线电视受 ...
- Android TV开发总结(五)TV上屏幕适配总结
前言:前面几篇总结一些TV上的小Sample,开源到GitHub:https://github.com/hejunlin2013/TVSample, 点击链接,可以持续关注.今天总结下TV上屏幕适配. ...
- Android TV开发总结(三)构建一个TV app的焦点控制及遇到的坑
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52835829 前言:上篇中,&l ...
- Android TV开发总结(二)构建一个TV Metro界面(仿泰捷视频TV版)
前言:上篇是介绍构建TV app前要知道的一些事儿,开发Android TV和手机本质上没有太大的区别,屏大,焦点处理,按键处理,是有别于有手机和Pad的实质区别.今天来介绍TV中Metro UI风格 ...
- Android TV开发总结(一)构建一个TV app前要知道的事儿
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52792562 前言:近年来,智能 ...
- 聊聊真实的 Android TV 开发技术栈
智能电视越来越普及了,华为说四月发布智能电视跳票了,一加也说今后要布局智能电视,在智能电视方向,小米已经算是先驱了.但是还有不少开发把智能电视简单的理解成手机屏幕的放大,其实这两者并不一样. 一.序 ...
随机推荐
- [leetcode]117. Populating Next Right Pointers in Each NodeII用next填充同层相邻节点
Given a binary tree struct TreeLinkNode { TreeLinkNode *left; TreeLinkNode *right; TreeLinkNode *nex ...
- 创建HTML元素的方法
第一种:使用 parent.appendchild()方法 HTML页面 <div id="div1"></div> JS文件 //第一步创建标签元素节点 ...
- 如何利用jQuery post传递含特殊字符的数据【转】
在jQuery中,我们通常利用$.ajax或$.post进行数据传递处理,但这里通常不能传递特殊字符,如:“<”.本文就介绍如何传递这种含特殊字符的数据. 1.准备页面和控制端代码 页面代码如下 ...
- PAT 1058 选择题(20)(代码+思路)
1058 选择题(20 分) 批改多选题是比较麻烦的事情,本题就请你写个程序帮助老师批改多选题,并且指出哪道题错的人最多. 输入格式: 输入在第一行给出两个正整数 N(≤ 1000)和 M(≤ 100 ...
- 讲真的,千万别得罪会PS的人
传说中有一种软件炒鸡可怕 那就是PS,专业术语是photoshop! 它能让你貌美如花 也能让你瞬间丑得掉渣 更可怕的是网络上大神的出现 简直让我们难以想象的厉害! 下面大家一起来欣赏一下 那些大神帮 ...
- adb占用
输入netstat -ano | findstr "5037" .然后会弹出提示告诉你哪些进程占用了该端口,记住非0地址的后面的数字 打开任务管理器,点击“进程“,“查看”-“选择 ...
- win7 一切软件都安装不上 解决 把他卸掉
KB2962872 控制面板,添加删除程序,查看已更新
- 情感分析snownlp包部分核心代码理解
snownlps是用Python写的个中文情感分析的包,自带了中文正负情感的训练集,主要是评论的语料库.使用的是朴素贝叶斯原理来训练和预测数据.主要看了一下这个包的几个主要的核心代码,看的过程作了一些 ...
- JavaScript的异步运行机制
----异步运行机制如下: 1.左右同步任务都在主线程上执行,形成一个执行栈 2.主线程值外,还存在一个任务队列,只要异步任务有了运行结果,就在任务队列中放置一个事件 3.一旦执行栈中的所有同步任务执 ...
- 2018.09.16 bzoj3757: 苹果树(树上莫队)
传送门 一道树上莫队. 先用跟bzoj1086一样的方法给树分块. 分完之后就可以莫队了. 但是两个询问之间如何转移呢? 感觉很难受啊. 我们定义S(u,v)" role="pre ...