android dp转px的公式_移动端Android设备上像素单位的调研

本文深入探讨了移动端Android设备上的像素单位,包括DPI、DP(密度无关像素)的概念及其相互关系。通过示例解释了不同DPI设备上如何使用DP进行等比例适配,并介绍了Android开发中如何处理不同分辨率和DPI的设备,以及Webview在不同宽度下的表现。此外,还涉及到了设备像素比DPR及其在浏览器中的应用。
摘要由CSDN通过智能技术生成

移动端设备上,不论是浏览器适配还是Android开发,最常见的需求是:不同设备不同分辨率上,同一份设计稿等比例适配的问题;另外,针对于大屏幕设备(如:pad),如何展现更多内容,呈现非等比例适配,也是一类需求;

本文的介绍对于浏览器开发和Android开发帮助都不大,做移动端适配的前端开发者请参考其它资料;作者旨在完成调研:通过示例来证明背后的关联关系;

以往其它作者的相关文章,一上来先介绍CSS像素,不太习惯;其实最好从硬件底层开始,自底向上介绍会理解更深刻;本文介绍先从DPI开始;

1. DPI(Dot Per Inch)每英寸点数/像素密度

这个词在打印行业中用的较多,代表:画布上单位面积内的物理实体的色块点数;

在打印中用于标识打印机的精度高低,用作打印机的分辨率单位;DPI值越高,表明打印机的打印精度越高。

例如:HP喷墨打印机最高标称分辨率是4800×1200dpi,这意味着在纸张的X方向(横向)上,每一英寸长度上理论上可以放置4800个墨点

在Android设备中,DPI既可以是一个物理实体概念(代表设备生产时每英寸有多少个色块点),也可以是一个虚拟逻辑概念(OS层面虚拟创建的每英寸色块点数);虚拟层的数值与物理层的数组可以不相同,这种非一一映射的情况可以通过OS底层驱动进行适配即可;

大家可以通过Android中的类DisplayInfo.java来理解,如下面代码所示:

    /**
     * The logical display density which is the basis for density-independent
     * pixels.
     */
    public int logicalDensityDpi;
    /**
     * The exact physical pixels per inch of the screen in the X dimension.
     * <p>
     * The value of this field is indeterminate if the logical display is presented on
     * more than one physical display.
     * </p>
     */
    public float physicalXDpi;
    /**
     * The exact physical pixels per inch of the screen in the Y dimension.
     * <p>
     * The value of this field is indeterminate if the logical display is presented on
     * more than one physical display.
     * </p>
     */
    public float physicalYDpi;

上图中Android OS会存储三个值:物理层的X方向DPI,物理层的Y方向DPI,以及逻辑层的像素密度相关DPI(下面会介绍);

开发者可以通过ADB命令查看这几个值,同时也可以使用ADB对变量logicalDensityDpi进行修改,以达到修改分辨率与密度无关像素DP的目的;

初期的移动设备上,常见为160dpi,即:每英寸拥有160个色块点;而PC端设备上,DPI范围在72~120之间;

参考:

Android官方:像素密度

百度百科:DPI

2. DIP/DP(Device Independent Pixel / Density Independent)设备独立像素/密度无关像素

同样的屏幕尺寸,拥有高低不同的DPI;如果软件设计中使用DPI作为单位,如果要保持一个图片在不同设备显示同样大小,那么设计稿需要针对不同的DPI提供不同的占比值;
比如:设计稿如果按照1px比1dpi的比例,在160DPI设备的设计稿为160px;在300DPI设备的设计稿为300DPI;
这样不好在于:

1) 提供多套设计稿;

2) 软件设计与物理设备映射紧密,如果出了新设备再适配就更麻烦;

所以出现新的方案:Android 1.8版本中增加的逻辑像素单位DP
例如:原有mdpi设备为160dpi,倍率定义为1,即:1px = 1dp;那么320x480px对应320x480dp;
例如:针对hdpi设备为240dpi,倍率定义为1.5,即:2px=1dp;那么480x800px对应320x533.33dp;
例如:针对xhdpi设备为320dpi,倍率定义为2,即:2px=1dp;那么640x960px对应320x640dp;

例如:针对xxhdpi设备为480dpi,倍率定义为3,即:3px=1dp;那么1080x1920px对应360x640dp;
例如:针对ldpi设备为120dpi,倍率定义0.75;,即:0.75px=1dp;那么240x320px对应320x426.66dp;
所以,Android开发中UI提供的设计稿,需要提供:mdpi * 最高倍率(一般为3) 的素材,才能完成向下的轻松适配;
上面的倍率称为:密度换算因子(Desity Conversion Factor),代表:该设备类型的DPI与基准DPI的比;

Android开发中常见使用DP作为单位,如果以360*640dp作为绘图尺寸,那么针对市场上不同DP宽度的设备,开发时就需要定义不同的布局声明;如:一个TextView组件在不同设备拥有不同的DP值;

参考:

Android官方:密度无关像素

Vinsol:开发者眼中的设计

Youtube(DIP介绍)

  • 最小宽度:

在部分手机的Android开发者选项中有一个"最小宽度"的设置,用于设置屏幕宽度的值,单位为DP;

6d74ffc11fee00e75f32f5f86d8c3dfa.png
开发者选项中的 最小宽度 选项


当修改设置中的"显示大小"时(用于适配老人等不同人群),这个DP值也跟着发生变化;
由此来看,DP值、屏幕分辨率、DPI值存在一定的换算关系:

最小宽度DP值 = 分辨率的宽px x 160 / DPI

参考:

DP与分辨率换算

  • ADB修改DPI与分辨率

针对Android设备,通过ADB命令可以查看/修改屏幕的分辨率,DPI;

命令:查看系统的分辨率与DPI:adb shell dumpsys window displays

命令:修改分辨率:adb shell wm size 1520x720

命令:修改DPI: adb shell wm density 300

命令:恢复设置: wm xxx reset

以作者的小米8青春版手机为例,手机设置中显示:

分辨率为:2280x1080像素,最小宽度为:392dp;

通过ADB命令查看,如下:

bc45c1f63f9be6f18d5b095d9d7d7095.png
mDisplayInfo=DisplayInfo{"内置屏幕", uniqueId "local:0", app 1080 x 2068, real 1080 x 2280, largest app 2198 x 2068, smallest app 1080 x 998, mode 1, defaultMode 1, modes [{id=1, width=1080, height=2280, fps=60.000004}], colorMode 7, supportedColorModes [7], hdrCapabilities android.view.Display$HdrCapabilities@40f16308, rotation 0, density 440 (403.411 x 402.166) dpi, layerStack 0, appVsyncOff 1000000, presDeadline 16666666, type BUILT_IN, state ON, FLAG_SECURE, FLAG_SUPPORTS_PROTECTED_BUFFERS, removeMode 0}

复制其中的文字可以看到:density 440 (403.411 x 402.166) dpi;

即:虚拟DPI为440,实际的物理DPI在XY分别为括号中的值

根据提示,此处的信息展现也是来自于本文最开始介绍的类DisplayInfo与类Display。

通过上面的公式也可以证明:DP与分辨率之间的换算关系;

392dp = 1080px * 160 / 440dpi;

当开发者通过ADB命令更新分辨率或者DPI时,会发现手机设置中的DP值也跟着发生改变,与公式计算一致;

3. PPI(Pixels Per Inch)每英寸像素数

可以用于衡量:观看移动设备时是否产生颗粒感;

乔布斯在iPhone 4发布会上对视网膜技术做介绍,分辨率达到300ppi以上,视网膜就无法分辨出像素颗粒点了;
与分辨率相关,计算方式:PPI = √(X^2 + Y^2)/ Z

(X:长度像素数;Y:宽度像素数;Z:屏幕英寸大小(对角线英寸长度))
例如:iPhone4的分辨率是960×640像素。 iPhone4采用3.5英寸IPS屏幕,同时加入了新的Retina Display(视网膜)显示技术,每英寸的面积里有326个像素;
PPI值 = √(960^2 + 640^2)/ 3.5 = 326PPI;通常电脑显示屏幕的分辨率为72ppi,iPhone4的分辨率为电脑的4倍多,所以显示会非常细腻。

上面这块源于网上内容,个人认为:如果没有设备高精度的DPI支持,那么此处的PPI是无意义的;

4. W3C中的viewport信息

在移动端浏览器中,最初为了在窄屏幕的设备上显示面向PC的网页内容,增加了viewport的meta信息;
如果viewport无声明,则默认屏幕width为980px,即屏幕可以滚动;

如果设置为device-width代表屏幕全宽,等同于screen.width;

<meta name="viewport" content="width=device-width">

使用作者的手机浏览器测试后,发现:

screen.width等于开发者选项中的最小宽度,即:dp值

相应的devicePixelRatio为 屏幕分辨率的宽度 / dp值;

参考:

MDN 980虚拟视口

PPK视口转述

然而实际上,在Android设备上Webview呈现并不需要占据屏幕全宽

那么当WebView在设备宽度为420dp的其中300dp上展现时(非全宽情况),此时的device-width会是多少呢?

经过测试,得到的结论是:

device-width代表视觉视口的宽度DP值;如果想要屏幕宽度DP值,那么通过screen.width获取

以下面的代码为例,读者可以针对不同的meta声明,查看不同单位的展示效果;

<!doctype html>
<html>
  <head>
    <title>首页</title>
    <meta name="viewport" content="width=device-width">
    <!--<meta name="viewport" content="initial-scale=1.0">-->
    <!--<meta name="viewport" content="width=980,initial-scale=1.0">-->
    <!--<meta name="viewport" content="initial-scale=2,user-scalable=no">-->
    <!--<meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no">-->
    <style>
      body {
        margin: 0;
      }

      .bg-gray {
        background-color: #d3d3d3;
      }
    </style>
  </head>
  <body>
    <!--<div class="bg-gray" style="width: 980px;">980px</div>-->

    <!--<div class="bg-gray" style="width: 490px;">490px</div>-->

    <div class="bg-gray" style="width: 300px;">300px</div>

    <div class="bg-gray" style="width: 50%;">50%</div>

    <div class="bg-gray" style="width: 100vw;">100vw</div>

    <div></div>

    <p id="num1"></p>
    <script>
      console.info(`innerWidth:`, window.innerWidth, window.outerWidth, window.devicePixelRatio, screen.width, screen)

      var text1 = [
        `document.clientWidth=${ document.documentElement.clientWidth}`,
        `window.innerWidth=${window.innerWidth}`,
        `window.outerWidth=${window.outerWidth}`,
        `window.devicePixelRatio=${window.devicePixelRatio}`,
        `screen.width=${screen.width}`
      ]
      document.getElementById('num1').innerHTML = text1.join('<br>')
    </script>
  </body>
</html>

同时,针对Android设备中,不同的Webview宽度(下图中上面为200dp,下面为300dp),来查看实际效果;

0565f5225add203c2f9326363f83d8f1.png
上面为200DP,下面为300DP

想要获取这个示例的读者,可以下载该APK示例项目进行测试与确认;

链接: https://pan.baidu.com/s/11CoYE2TuvTiqxmnGzUz89A 提取码: 3bs1

5. DPR 浏览器中的devicePixelRatio 设备像素比

MDN定义为:CSS像素与物理像素的比率;

根据上面推算,分辨率中的宽度像素值就是CSS像素值;物理像素值指的是DP值;
即:DPR = 分辨率中的宽度值 / 最小宽度DP值

以作者手机为例:2.75dpr = 1080px / 393dp;

当通过ADB命令修改分辨率与DPI后,相应DPR也会跟着变化,此处不再赘述;

参考:

Github中某作者的理解

第三代移动端布局方案

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值