High DPI

rose-sdk 发布于 2016/05/17 19:12
阅读 742
收藏 0
一、为什么会出现High DPI问题
首先解释什么是DPI。DPI是Dots Per Inch缩写,表示每英寸点数,这里的点(Dot)指什么?对面向PC、手机、Pad编程的程序员来说,它等同像素(Pixel),于是DPI就等同PPI。

当前流行的DPI是多少,让以两款电脑为例有个直观认识。一商务笔记本,13.3x8.3英寸屏,最大分辨率1920x1080,由它可算出水平、垂直DPI大概是144(1920/13.3)、130(1080/8.3)。苹果的一款MacBook Air,13.3x8.3英寸屏,最大分辨率1440x900,它水平、垂直DPI分别是108、108。

接下说苹果营销出的一个概念:Retina屏(视网膜屏)。单从DPI这个参数来说,Retina屏是指它的DPI超过人眼能识别极限的最高DPI,我们不关心这个DPI是不是真的超过人眼分辨极限,但不得不承认的是,Retina屏的DPI的确是基本做到了普通屏的2倍。举个例子,当前一款MacBook Pro,13.3x8.3英寸屏,最大分辨率2560x1600,那它的水平、垂直DPI到达了192,基本是同期Air的两倍。

现在来讨论同一数量像素下在Air和Pro分别是多少英寸。假设有一个按钮,程序设定它是360x360像素,那它在Air的实际尺寸是3.33x3.33英寸/8.46cm,在Pro则是1.87x1.87英寸/4.76cm。——到此对High DPI问题会有初步认识了:由于不同DPI,使得同一App在不同显示器上显示时会出现很不一样的物理尺寸。就拿这两款苹果笔记本,Air上看去正常的按钮,换Retina上就小很多。

以上讨论是电脑屏,手机、Pad屏也一样存在DPI。例如iPhone6,对角线是4.7英寸(屏尺寸大概是4.09x2.3),它的水平、垂直DPI都是326。仍然以360x360按钮为例,在iPhone6上则变成1.1x1.1英寸(2.8cm)。以下表格小结了同一像素数在不同设备上的物理尺寸。

设备 DPI 像素数 物理尺寸
MacBook Air 108 360 3.33英寸/8.46cm
MacBook Pro 192 360 1.87英寸/4.76cm
iPhone6 326 360 1.1英寸/2.8cm

High DPI问题根源是用户在意的是物理单位表示的尺寸,程序员关注的是像素表示的尺寸,而关联物理单位和像素的DPI在各设备不同,使得要能让同一App在这些设备都能正常使用的话须进行额外处理。

二、解决High DPI方法:放大倍数(hdpi_scale)
让思考这样一个问题,对同一个按钮,如何让在MacBook Air、MacBook Pro看去是同一物理尺寸?很快能想到办法,按钮的像素数在Pro时是Air像素数乘上2。办法虽然简单,但的确是各操作系统在使用的解决High DPI方法。

那放大倍数到底是多少,有些是操作系统决定,像iOS,它规定iPhone 5/6是2、iPhone6 Plus是3。Android、Windows则由程序员自个定,不过为缩放图像简单,真正到显示时倍数要取整数。以下是Android定义的density(基本等同hdpi_scale)、DPI值之间关系,它用了一个等式:DPI = density * 160。

density 名称 DPI
0.75 ldpi 120
1.0 mdpi 160
1.5 hdpi 240
2.0 xhdpi 320
3.0 xxhdpi 480
4.0 xxxhdpi 640

对Windows系统一般取2,一来是考虑到它的DPI相比手机来说不是很大,二来Windows有个High DPI-unaware概念,对属于High DPI-unaware类型App,它会默认用2去放大。接下就让说说High DPI-unaware。Windows把App分为两类:High DPI-aware和High DPI-unaware,App可调用SetProcessDpiAwareness(Win8.1开始出现)这个API让自个归属到哪种类型。

High DPI-unaware是告诉系统,我这App不支持高清屏,如遇上高清屏请通过DWM(Desktop Window Manager)虚拟化帮我去实现。此种方式的高DPI支持具体过程是这样的,比如当前系统的DPI是192(200%),程序运行时,系统会告诉你当前DPI仍然是96(100%),所以程序会仍然按照96的方式进行绘画,而且调用系统API时,得到的坐标、窗口尺寸都是按96来的。当我们画完之后,DWM再对整个窗口进行200%放大后画到屏幕上,这样看起来程序就自动支持高DPI了。 这种方式对那些非高清屏上开发却依旧要在清高清屏运行的App很有用,像在XP、Win7开发的App,正因为如此,App默认的工作方式是High DPI-unaware。

这种方式看起来很美妙,但有严重缺点,经过放大后的内容看起来会变模糊,比如文字会有明显锯齿。既然DWM虚拟化用户效果不怎么好,那么很多时候就得向操系统宣称自个能支持高DPI,请直接告诉我真实DPI,至于遇到的屏是192还是108,我自个去处理,这种类型的App就是High DPI-aware。

虽然不叫DWM,iOS也有类似这样功能的模块,它也可把App分为那两类。不过由于DWM会导致图像变模糊这个致命缺点,往后程序必将都是High DPI-aware。

回到方法的源头,让引入两个概念,配置尺寸和显示尺寸。
  • 配置尺寸(Config Size):定义控件时使用的尺寸。设定值时参考一条规则:能满足最低要求的DPI。
  • 显示尺寸(Display Size):控件最终显示出来的尺寸。是配置尺寸乘上放大倍数,在值上,放大倍数等于1时就是配置尺寸。

原贴:http://www.libsdl.cn/bbs/forum.php?mod=viewthread&tid=22&extra=page%3D1

加载中
返回顶部
顶部