zoukankan      html  css  js  c++  java
  • 关于android上dpi/screen-size的厘清解释

    android定义了四种screen-size:

    small

    normal

    large

    xlarge

    同时定义了六种dpi级别:

    ldpi (low) ~120dpi
    mdpi (medium) ~160dpi
    hdpi (high) ~240dpi
    xhdpi (extra-high) ~320dpi
    xxhdpi (extra-extra-high) ~480dpi
    xxxhdpi (extra-extra-extra-high) ~640dpi

    定义这些级别的目的在于更好地组织资源,以适应不同的设备。参见:http://developer.android.com/guide/practices/screens_support.html#range

    系统在运行我们的app时,会自动根据当前设备的级别,来加载合适的资源,而我们就需要为不同级别准备各自的资源,如为大屏幕上提供一个并列放置两个view的layout,而小屏幕上则一次只显示一个view。

    要做到这一点,我们必须要知道,给定一个设备,如何判断它是哪个级别的?然后才能有的放矢,把相应的资源放在正确的级别目录中。

    首先看screen size,这个级别会影响layout模板的选取,即指定一个R.layout.id_XXX时,到底是从res/layout下加载,还是从res/layout-large下加载呢?

    先看官方给的图:

    第一排是关于size的分档,在这里,各个档是有重叠的,也就是一个大概的范围。

    但是我们知道,程序运行时的加载逻辑必须是精确的,针对每一个设备必须获得一个确定的值,以判定它是哪个级别,然后才知道要加载哪些资源。

    以上图论,如果我们有一个3.3"的手机,那它到底是small还是normal呢?就无法判断了。

    所以,必然要有更准确的计算方法,而这个方法就牵扯到dpi了。

    dpi:dot per inch,就是指每英寸上有多少个像素点,要计算这个值,就要知道它的物理尺寸和物理分辨率(也就是全屏有多少实际像素点,或者就是说能发光的元件)

    比如我们建一个虚拟设备来看:

    它的物理分辨率是720x1280,物理尺寸是4.7"

    可能有人疑问,物理尺寸不也是有宽和高吗,怎么才一个值?这个4.7",是对角线的长度。用对角线来做标称,好处是容许更自由的宽高组合吧。

    那么要计算这个dpi,按常理就没法算了,因为1个对角线值无法确定惟一的宽高。

    但是换一个思路,将面积密度换成线密度,即用对角线上的像素数量来除以对角线长度,其值应该是一致的,所以dpi计算如下:

    dpi = sqrt(pixel_width^2+pixel_height^2)/diagonal = sqrt(720^2+1280^2)/4.7 = 312.5

    对照上表,可知其dpi级别为xhdpi,与工具界面上显示的一致。

    知道了dpi,那么图片类资源的加载目录就知道了,此例中就是res/drawable-xhdpi,但是layout类资源又如何呢?

    layout的选取标准与图片资源不同,并不以dpi级别为准,而是要看screen size的级别。

    上面在讲screen size分类方法时转而插入对dpi解释,正是为了这里能说清其含义。

    实际上官方对screen size的分类标准如下:

    • xlarge screens are at least 960dp x 720dp
    • large screens are at least 640dp x 480dp
    • normal screens are at least 470dp x 320dp
    • small screens are at least 426dp x 320dp

    这里给出的宽、高值其实并无单独比较意义,最终结果是看它的乘积。

    也就是说最小的屏幕要有426*320=136,320个dp,而要想成为一个中等屏幕则至少需要470*320=150,400个dp,列表如下:

    smal = 136,320

    normal = 150,400

    large = 307,200

    xlarge = 691,200

    现在问题来了,dp又是什么,和dpi什么关系?针对上例这个设备,它又有多少个dp呢?

    先回想一下dpi,它本身是一个比率值,说的是每英寸上有多少个像素点,这是刻划设备能力的一种属性。

    然而很多时候能力的绝对值对一般人认知理解来说并不直观(虽然这个例子并不合适,dpi还是很直观的),其相对值才更具有意义。

    那么选取第一台android设备为基准,它的dpi是160,其它设备的dpi与160相比,得到一个比率值scale,就是该设备的(dp-)scale,

    那么设备的dp则定义为:

    dpx = pixel_width/scale

    dpy = pixel_height/scale

    此例中则其 scale=312.5/160=1.95,dpx=720/scale=369.2,dpy=1280/scale=646.4

    也就是以dp单位来衡量,此虚拟设备有一个369 x 646的屏幕,现在可以来计算它的screen size级别了:dp = dpx * dpy = 369 * 646 = 238,374

    查上表可知介于150,400和307,200之间,所以它的screen size为normal,当加载layout时,优先使用res/layout里的资源(而非small/large/xlarge)。

    定义和计算过程清楚后,再回头审视一下dp的含义,为什么要通过如此曲折的方式来定义这样一个单位。

    1、其实从物理分辨率到dp(也就是screen size),只是转换了一下手段,但目的还是一样:就是要解决“数清楚屏幕上到底有多少个点,然后我们的ui面板要做多少个点”这个问题。

    2、为什么不直接用“物理像素”,会有什么问题?因为不同设备物理尺寸与分辨率之比差别很大,比较极端的情形是,两个分辨率相同的设备,尺寸却差一半,比如这两:

    如果以物理像素定义一个面板为400*600px大小,也就是全屏一半的样子,在10"的tablet上看起来大小正合适,而在4.7"的手机上,那就是小小的一砣,这一砣的物理占地只有tablet上1/16!

    如果tablet上的视觉效果是合理的,那么很难想象肉眼如何适应这1/16的同质元素

    但是改用dp为单位来描述,结果会是如何呢?(计算结果可以在这个网页方便获取:https://www.sven.de/dpi/)

    对前者,dpi=149.5,scale~=1.0,screen size(dp)=800*1280

    对后者,dpi=317.6,scale~=2.0,screen size(dp)=384*640

    如果我们需要一个在tablet占地1/4(也就是宽高各1/2)的区域,那么其dp大小应为400*640

    现在计算其在phone上的占地,先换算为像素大小,w=400*2.0=800,h=640*2.0=1280

    即这是一个800*1280像素的区域,几乎刚好是整个Phone屏幕大小(考虑上面计算scale时的舍入误差)

    而这个大小,在物理尺寸上刚好和tablet上的1/4是一样的。

    可见,使用dp来描述大小的优势在于:确保了该区域在不同分辨率和物理尺寸的屏幕上,其物理面积是一样大的!

    而物理面积,正是肉眼观察舒适度的重要衡量标准——而不仅仅是分辨率,相信大家都有体会,很多高清屏手机虽然足够细腻,但如果用来看电子书其实很废眼,远不如较低分辨率但更大尺寸的平板)

    现在,dp的含义和好处清楚后,还有最后一个问题:如果真要设计一个面板,到底该给它多少dp呢?dp既是一个虚拟单位,如何直观地以它来估算大小呢?

    其实,可以就用dp的来源——第一个android设备的大小作为基准来考虑,它是一个大小为3.2",分辨率为320*480的手机:

    在它上面,1个dp就是1个像素。所以,要弄多大的界面,就以它为参考咯!

  • 相关阅读:
    Opencv(1)介绍篇
    植被覆盖度制图
    GIS应用开发AO(2)-空间分析ITopologicalOperate
    GIS应用开发AO(1)_普通几何图形绘制
    初识机器学习-人脸识别
    ArcGIS API for javascript4.3——RouteTask
    javascript学习(1)随机点名应用
    生活感悟之六
    生活感悟之五
    生活感悟之四
  • 原文地址:https://www.cnblogs.com/wellbye/p/4628933.html
Copyright © 2011-2022 走看看