前言
Android 的屏幕适配是指适配不同机顶盒 UI 框架层输出的分辨率和 dpi,而不是适配不同分辨率的电视机(电视机的适配交由机顶盒本身完成,和各个应用无关)。
获取机顶盒 UI 框架层输出的分辨率和 dpi
可以通过以下代码获取机顶盒UI框架层实际输出的分辨率(对应代码中的 width * height
),以及输出的 PPI(DPI)(对应代码中的 densityDpi
)。
DisplayMetrics metric = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(metric);
// 屏幕宽度(像素)
int width = metric.widthPixels;
// 屏幕高度(像素)
int height = metric.heightPixels;
// 屏幕密度(1.0 / 1.5 / 2.0)
float density = metric.density;
// 屏幕密度DPI(160 / 240 / 320)
int densityDpi = metric.densityDpi;
String info = "机顶盒型号: " + android.os.Build.MODEL + ",\nSDK版本:"
+ android.os.Build.VERSION.SDK + ",\n系统版本:"
+ android.os.Build.VERSION.RELEASE + "\n屏幕宽度(像素): " +width + "\n屏幕高度(像素): " + height + "\n屏幕密度: " +density+"\n屏幕密度DPI: "+densityDpi;
Log.d("System INFO", info);
例子
以一个小例子说明:
- 切图应该放哪个 drawable 文件夹下?
- UI 应该以什么标准出图?
- UI 出的标注图 px 和 dp之间如何转换?
比如:某款易思腾的机顶盒,通过如上代码,获取到的分辨率为 1280 * 720
DPI 为 160dpi
,但是机顶盒连接的是 4K 电视,电视的分辨率为 3840 * 2160
),此时 :
- 切图应该放在
drawable-mdpi
文件夹下。因为,android 系统会根据densityDpi
去不同的drawable-XXXX
文件夹下获取图片,根据下图,160dpi
对应drawable-mdpi
。 - 不考虑适配其他机顶盒的情况下,UI 应该按照
1280 * 720
出图,而不是电视的3840 * 2160
出图。因为,app 在机顶盒上实际输出的像素就只有1280 * 720
像素,而在 4K 电视上 4K 显示效果是机顶盒将系统 UI 框架的1280 * 720
像素的输出优化放大道3840 * 2160
像素,以及 4K 电视的优化显示的结果。编写代码时对应的 app 全屏的页面只有1280 * 720
像素,并没有3840 * 2160
像素。 -
160dpi
下,1px
对应1dp
。
依据 支持多种屏幕 - Google 官方文档(需翻墙),**dpi
对应的实际 dpi 如下图所示。
一些盒子分辨率列表
下图是一些盒子分辨率列表(来自Android TV 开发总结(五) TV 上屏幕适配总结)
对上图中的机顶盒按照宽度( dp )整理如下:
宽度(dp) | 机顶盒型号(dpi) |
---|---|
1920dp | youku(160dpi) |
1280dp | i71s(240dpi)、海信电视(240dpi)、i71(160dpi)、Letv New C1S(160dpi)、XMATE_A88(迪优美特)(160dpi)、开博尔C9(KBE_H8)(160dpi)、英菲克i9(160dpi) |
961.5dp | 小米二代(213dpi) |
960dp | MiBox3(320dpi)、MiBox3_Pro(320dpi)、华为M321(320dpi) |
可以看出宽度大部分的是 1280dp
和 960dp
两个尺寸,还有youku (1920dp
)和小米二代(961.5dp
)的两个奇葩尺寸。1280dp
和 960dp
的差距还是蛮大的。所以,针对不同宽度,得分别标注不同的值。通过 value-w****dp
适配不同的机顶盒,对照表如下:
value | 机顶盒 |
---|---|
value-w1920dp | youku(160dpi) |
value-w1280dp | i71s(240dpi)、海信电视(240dpi)、i71(160dpi)、Letv New C1S(160dpi)、XMATE_A88(迪优美特)(160dpi)、开博尔C9(KBE_H8)(160dpi)、英菲克i9(160dpi) |
value-w961dp | 小米二代(213dpi) |
value-w960dp | MiBox3(320dpi)、MiBox3_Pro(320dpi)、华为M321(320dpi) |
切图的适配比较麻烦一点,在相同 160dpi
屏幕密度下,有 1920dp
和 1280dp
两种宽度。如果 1920dp
宽度的 UI 是按 1280dp
UI 等比例放大出来的话,在 1280dp
下 100dpx100dp
宽高的图片,在 1920dp
下宽高就变成了 150dpx150dp
。所以,对占大都数的 1280dp 160dpi
分辨率的机顶盒,对应的切图放在 drawable-mdpi
下,对 youku 这种奇葩分辨率的机顶盒,专门用 drawable-mdpi-1920x1032
放置切图。所有机顶盒切图放置对应表格如下:
drawable | 机顶盒 |
---|---|
drawable-mdpi | i71(160dpi)、Letv New C1S(160dpi)、XMATE_A88(迪优美特)(160dpi)、开博尔C9(KBE_H8)(160dpi)、英菲克i9(160dpi) |
drawable-mdpi-1920x1032 | youku(160dpi) |
drawable-213dpi | 小米二代(213dpi) |
drawable-hdpi | i71s(240dpi)、海信电视(240dpi) |
drawable-xhdpi | MiBox3(320dpi)、MiBox3_Pro(320dpi)、华为M321(320dpi) |
机顶盒从 drawable 获取切图的顺序如下(来自Android TV 开发总结(五) TV 上屏幕适配总结):
- 语言( zh-rCN )
- smallestWidth 最短可用宽度(与屏幕方向无关)
- available width(w-<N>dp)(与屏幕方向有关)
- values/drawable-1920x1080
- drawable-213dpi
- ldpi/mdpi/hdpi/xhdpi/xxhdpi
机顶盒切图放置位置和手机不同
UI 按照给手机出切图的方式导出的 xxhpi、xhdpi、hdpi、mdpi等切图,不能直接放置在对应 dpi 的 drawable 目录下。
比如,UI 以 1080 * 1920
为基准,导出的一比一的切图,在手机上,对应的是 xxhdpi
,因放置到手机的 drawable-xxhdpi
文件夹中。而在机顶盒上(假设机顶盒分辨率为 1280 * 720 160dpi
或 1920 * 1080 240dpi
),对应的应该是 hdpi
,因放置到 drawable-hdpi
文件夹中,机顶盒需要其他切图,应该以 hdpi
为基准进行放大或缩小出图。
总结
为了适配大部分机顶盒,UI 应该按照 1920 * 1080
出图,1920 * 1080
效果图导出的1比1的切图,对应的是 hdpi
(而非手机开发时候的 xxhdpi
)。给 drawable-xhdpi
、drawable-hdpi
、drawable-mdpi
的切图。编码时,在 value-w1280p
、 value-w960p
下分别设不同的值(value-w960p
下的值可按 value-w1280p
中的值等比例缩放获得)。
其他
Android TV 开发遇到的图片失真问题以及对应的解决办法
美术在出图的时候,适当的给图片周围增加几个个像素的透明区域,然后给这个区域做一个渐变的效果(根据具体图片具体内容来决定,逐渐向图片边缘淡化直至透明),最终显示的结果就是图片周围会有一圈模糊的图像,但是能够消除较大部分的锯齿。
相关文章
Android TV开发总结(五) TV 上屏幕适配总结
智能电视 TV 分辨率处理方案--第 1 问
智能电视 TV 盒子开发选择--第 2 问
Android 电视机(机顶盒)初次开发的一些经验分享