dp的定义原理和dpi,ppi,px,sp之间的区别

刺骨的言语ヽ痛彻心扉 2023-07-14 10:42 72阅读 0赞

扩展知识:
1080p和720p是什么意思
百度百科分辨率中最后一段话不明白的,可以参考这里

在开始讲解dp前,先来认识一些概念:

相关尺寸单位

px(pixel 像素):屏幕上的点,一般HVGA代表320x480像素

in(inch 英寸):长度单位: 英寸

1英寸(in)=2.54厘米(cm)

分辨率

“分辨率”被表示成每一个方向上的像素数量,比如640X480等。某些情况下也可以同时表示成“每英寸像素”(ppi)以及图形的长度和宽度。比如72ppi,和8X6英寸。

描述分辨率的单位有:(dpi点每英寸)和ppi(像素每英寸)。(PPI和DPI都是分辨率。PPI用于显示器,一个像素一个格子。DPI用于打印机,“每英寸墨点”)

  • - ppi(pixels per inch):单位英寸上的像素数量,是物体的属性。公式为: ppi = 屏幕对角线像素数(px) / 屏幕对角线长度(in)
  • - dpi(dots per inch):单位英寸上的像素数量,是单位。公式为: dpi = 屏幕对角线像素数(px) / 屏幕对角线长度(in)。
  • ppidpi经常会出现混用现象。它们都是用来描述屏幕的属性。从技术角度说,“像素”(P)只存在于计算机显示领域,而“点”(d)只出现于打印或印刷领域。

    描述手机屏幕属性使用ppi,在开发过程中drawable 各个文件对应的是dpi。这两个单位的计算方法一样,描述不一样,只是因为使用的场景不一样

  1. **QVGA** : 分辨率为 320\*240 (Quarter VGA即四分之一)
  2. **HVGA** :分辨率为 320\*480 ( Half-size VGA即一半)
  3. **VGA** : 分辨率为 640\*480 (全称Video Graphic Array)
  4. **WVGA** 分辨率为 800\*480 (Wide VGA 很多网页的宽度都是800,所以WVGA的手机屏幕会更加适合于浏览网页)
  5. **FWVGA** :分辨率为 854\*480 手机c8813
  6. 英寸是一个物理单位,大家平常说的手机屏幕4.3英寸,4.5英寸指的是屏幕对角线的长度,如下图所示:
  7. ![这里写图片描述][20150826183248820]
  8. 分辨率480 x 800,屏幕尺寸4.3英寸和分辨率540 x 960,屏幕尺寸4.5英寸的**DPI**分别是:
  9. ![这里写图片描述][20150826183305528]
  10. ## 与分辨率无关的度量单位 ##
  11. Android支持下列所有单位:
  12. * **dp**(dip : device independent pixels(设备独立像素)):一种基于屏幕密度抽象长度单位。**在每英寸160点的显示器上,1dp = 1px。**(注意和上面介绍的dpi区分)
  13. * **sp**(与刻度无关的像素):与dp类似,但是可以根据用户的字体大小首选项进行缩放。
  14. --------------------
  15. 下面通过几个问题,来让你深入了解dp的定义和
  16. ## 一、为什么规定160dpi规格的显示器上,1dp = 1px? ##
  17. 答:这个在Google的官方文档中有给出了解释,因为第一款Android设备(HTCT-Mobile G1)是属于160dpi的。
  18. **为什么说是属于160dpi?**
  19. T-Mobile G1DPI,其实它准确的PPI不等于160G1的配置信息如下:
  20. **屏幕尺寸**:3.2 寸(8.1 厘米)
  21. **分辨率**:320 x 480HVGA
  22. 如果按照上面的计算方式,T-Mobile G1应该属于180dpi,使用计算器,计算结果为180.277564dpi
  23. 为什么不直接用180作为基准(mdpi)而是160呢?
  24. 180上下不好做适配,但是160无论是乘以0.5/2/1.5都很好适配,这就是为什么是属于而不是等于。
  25. 为什么要选一个160dpi作为标准呢?
  26. Android其实为了不至于为每一个设备制造商做适配(其实资源文件的分包就算适配了:drawable-hdpidrawable-ldpi),将不同屏幕大小和不同dpi的设备大致划分为四类,如下图:
  27. ![这里写图片描述][20150826183358351]
  28. 大家可以看到T-Mobile G1的参数属于mdpi区域的,以上就是取160dpi作为基准的原因。
  29. 在编程过程中获得的density,与自己手动计算出来的dpi是不一样的,因为这里进行了分类,所以不同dpi设备上,比例缩放有一点点差异,详见下面第三点
  30. ## 二、dp ##
  31. 如果有兴趣可以看一下这个类的源码(网址):[GrepCode: android.util.DisplayMetrics (.java)][GrepCode_ android.util.DisplayMetrics _.java] ,这个类中有很详细的dpi相关的成员函数和变量,下面的代码是在开发时获取dpi的代码,
  32. DisplayMetrics metrics = new DisplayMetrics();
  33. getWindowManager().getDefaultDisplay().getMetrics(metrics);
  34. iDensity = (int)( metrics.density * 160 );
  35. 1
  36. 2
  37. 3
  38. ## 2.1、为什么要引入dp? ##
  39. 答:dp实际是dipdensity independent pixel),独立密度像素,意思就是与density密度(dpi)无关。
  40. 我使用dp作为单位设置控件,不管你什么屏幕大小,多大的dpi,显示的效果始终保持一致。
  41. **举例:**
  42. 不使用dp,使用px的效果
  43. 1. 假如我们不引入dp,还是使用原始的px,现在我们需要在手机屏幕上绘制一条直线,在160dpi(每英寸160个像素点),宽度是1英寸的手机上,我们设置这条直线长度是160px(占据160个像素点),也就是直线长度正好是手机的宽度
  44. 2. 但是240dpi(一英寸240个像素点),宽度是1英寸的手机上安装了这个app,长度只有屏幕宽度的2/3
  45. 类似于下面这样的效果:
  46. ![这里写图片描述][20150826183420610]
  47. 使用dp的效果
  48. * 上面这张图来自Google的开发网站。如果引入dp这个单位,这种问题就不会发生了,还是以上面的例子说明,如果在160dpi的设备上使用的是160dp,无论移植到240120dpi上显示效果都是一致的。效果如下图:
  49. ![这里写图片描述][20150826183432677]
  50. **为了使用户界面能够在现在和将来的显示器类型上正常显示,建议大家始终使用sp作为文字大小的单位,将dp(即dip)作为其他元素的单位。当然,也可以考虑使用矢量图形,而不是用位图。**
  51. ## 2.3、px和dp的换算公式 ##
  52. **pxdp的换算公式:px = dp \* (dpi / 160)**
  53. --------------------
  54. **dp**: dp也就是dip:device independent pixels(设备独立像素)
  55. **dp是一种与密度无关的像素单位**,在每英寸160点的屏幕上,1dp = 1px
  56. 不同设备有不同的显示效果,这个和设备硬件有关,一般我们为了支持WVGAHVGAQVGA 推荐使用这个,不依赖像素
  57. <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="@string/clickme" android:layout_marginTop="20dp" />
  58. 1
  59. 2
  60. 3
  61. 4
  62. **sp**: scaled pixels(刻度像素). 主要用于定义字体的大小,而从来不再layout上使用
  63. <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:textSize="20sp" />
  64. 1
  65. 2
  66. 3
  67. **px**:pixels(像素). 不同设备显示效果相同,一般我们HVGA代表320x480像素,这个用的比较多
  68. ## 三、为什么手工计算dp对应的px大小与实际显示的px不一样 ##
  69. 1、实际不同的手机上控件的大小和屏幕比例感觉都差不多,因为Android把屏幕大小,像素密度等接近的归为一类dpi,所以实际显示的px和手工计算出来的px尺寸有一定差异。
  70. 由于Android的划分,使用dp为长度单位,导致计算出来的px与实际显示px不符合
  71. 设备一:Sony Z2 屏幕尺寸:5.2in 屏幕分辨率:1080\*1920 DPI424
  72. 设备二:华为 Mate 7 屏幕尺寸:6.0in 屏幕分辨率:1080\*1920 DPI367
  73. 套用公式:px = dp \* (dpi / 160),开发人员写一个高度为48dp的控件。
  74. Sony Z2上的渲染像素为:**48\*424/160=127.2px**
  75. 在华为 Mate 7上的渲染像素为:48\*367/160=110.1px
  76. **这显然很荒谬:**
  77. 1.出现小数的像素个数,而像素的最小单位是1,在设备上无法显示。
  78. 2.根据实际截图测试,Sony Z2实际渲染像素为144px(@3x),华为 Mate 7 实际渲染像素为144px(@3x)。
  79. 也就是说,实际的渲染像素并不是按照此公式计算的。而是按照渲染倍率(即@2x,@3x)来计算的。
  80. 实际的渲染像素如下:
  81. Sony Z2上实际渲染像素为:48@3x=144px
  82. 在华为 Mate 7上实际的渲染像素为:48@3x=144px
  83. **原因:**
  84. densityn. 密度
  85. 手机adensity = 手机appi/160
  86. 160ppi为基准,160ppi对应的density1.0mdpi),240ppi对应的density1.5hdpi),320ppi对应的density2.0xhdpi)…
  87. 最关键的一点是,真机屏幕的ppi会取和以上标准最相近的标准ppi!然后density按照最相近的ppi来定。
  88. <table>
  89. <thead>
  90. <tr>
  91. <th>限定符</th>
  92. <th>说明</th>
  93. <th>比例</th>
  94. </tr>
  95. </thead>
  96. <tbody>
  97. <tr>
  98. <td>ldpi</td>
  99. <td>适用于低密度 (ldpi) 屏幕 (0dpi~120dpi) 的资源。</td>
  100. <td>1dp=3/4px</td>
  101. </tr>
  102. <tr>
  103. <td>mdpi</td>
  104. <td>适用于中密度 (mdpi) 屏幕 (120dpi~160dpi) 的资源。(这是基线 密度。)</td>
  105. <td>1dp = 1px</td>
  106. </tr>
  107. <tr>
  108. <td>hdpi</td>
  109. <td>适用于高密度 (hdpi) 屏幕 (160dpi~240dpi) 的资源。</td>
  110. <td>1dp = 1.5px</td>
  111. </tr>
  112. <tr>
  113. <td>xhdpi</td>
  114. <td>适用于超高密度 (xhdpi) 屏幕 (240dpi~320dpi) 的资源。</td>
  115. <td>1dp = 2px</td>
  116. </tr>
  117. <tr>
  118. <td>xxhdpi</td>
  119. <td>适用于超超高密度 (xxhdpi) 屏幕 (320dpi~480dpi) 的资源。</td>
  120. <td>1dp = 3px</td>
  121. </tr>
  122. <tr>
  123. <td>xxxhdpi</td>
  124. <td>适用于超超超高密度 (xxxhdpi) 屏幕 (480dpi~640dpi) 的资源。</td>
  125. <td>1dp = 4px</td>
  126. </tr>
  127. </tbody>
  128. </table>
  129. 2、这是一个假设、使用手动计算出的dpi(通过公式dpi = 屏幕对角线像素数(px / 屏幕对角线长度(in)),相同dp在不同手机显示的都是相同物理尺寸,而不是相同的屏幕占比。
  130. **pxdp的换算公式:px = dp \* (dpi / 160)**
  131. px = dp \* (dpi / 160) = dp \* (px(屏幕对角线像素) / in(屏幕尺寸) / 160)
  132. 因此在dp不变,in不变时,屏幕对角线像素数量越大,控件的px越大
  133. 下面举个例子:
  134. <table>
  135. <thead>
  136. <tr>
  137. <th>手机类型</th>
  138. <th align="left">屏幕对角线像素个数</th>
  139. <th align="left">屏幕尺寸</th>
  140. <th align="center">dpi</th>
  141. <th align="left">160dp显示的像素个数</th>
  142. <th align="left">160dp显示的英寸</th>
  143. <th>160dp在屏幕对角线的占比</th>
  144. </tr>
  145. </thead>
  146. <tbody>
  147. <tr>
  148. <td>手机A</td>
  149. <td align="left">480px</td>
  150. <td align="left">3in</td>
  151. <td align="center">160dpi</td>
  152. <td align="left">160个</td>
  153. <td align="left">1in</td>
  154. <td>1/3</td>
  155. </tr>
  156. <tr>
  157. <td>手机B</td>
  158. <td align="left">640px</td>
  159. <td align="left">2in</td>
  160. <td align="center">320dpi</td>
  161. <td align="left">320个</td>
  162. <td align="left">1in</td>
  163. <td>1/2</td>
  164. </tr>
  165. <tr>
  166. <td>手机C</td>
  167. <td align="left">960px</td>
  168. <td align="left">3in</td>
  169. <td align="center">320dpi</td>
  170. <td align="left">320个</td>
  171. <td align="left">1in</td>
  172. <td>1/3</td>
  173. </tr>
  174. </tbody>
  175. </table>
  176. 即使使用dp,也不能保证理论上,所有手机都能完美适配.
  177. 本质上是规定了160dp等于1in,但是谷歌内部对手机进行了很好的dpi划分,所以使用dp才成为一种解决手机适配的方法,你可以多拿几款手机进行验证
  178. 那为什么使用dp作为长度单位,可行呢?
  179. 1. 有可能是在手机发展的道路中,不会出现手机A到手机B的情况,就算有估计也不会出现这么大的反差(屏幕缩小1/3,分辨率增加1/2),
  180. 2. 还有就是我估计手机厂商内置已经设置好了dpi的值,谷歌在划分屏幕的归类时,也已经处理好这些问题了,关于如何划分手机对应的dpi,请参考[这里][Link 3]
  181. 本质上是规定了160dp等于1in,但是谷歌内部对手机进行了很好的dpi划分,所以使用dp才成为一种解决手机适配的方法
  182. **总结:dp也就是dip。这个和sp基本类似。如果设置表示长度、高度等属性时可以使用dpsp。但如果设置字体,需要使用spdp是与密度无关,sp除了与密度无关外,还与scale无关。**
  183. 如果屏幕密度为160,这时dpsppx是一样的。1dp=1sp=1px,但如果使用px作单位,如果屏幕大小不变(假设还是3.2寸),而屏幕密度变成了320。那么原来TextView的宽度设成100px,在密度为3203.2寸屏幕里看要比在密度为1603.2寸屏幕上看短了一半。
  184. 但如果设置成100dp100sp的话。系统会自动将width属性值设置成200px的。也就是100 \* 320 / 160。其中320 / 160可称为密度比例因子。也就是说,如果使用dpsp,系统会根据屏幕密度的变化自动进行转换.
  185. ## px 和 dp 互转换代码 ##
  186. package com.hujl.util;
  187. import android.content.Context;
  188. public class DensityUtil {
  189. /** * 根据手机的分辨率从 dp 的单位 转成为 px(像素) */
  190. public static int dip2px(Context context, float dpValue) {
  191. final float scale = context.getResources().getDisplayMetrics().density;
  192. //因为有的dpi为160的1.5倍,所以计算完后,为了没有小数,加0.5
  193. return (int) (dpValue * scale + 0.5f);
  194. }
  195. /** * 根据手机的分辨率从 px(像素) 的单位 转成为 dp */
  196. public static int px2dip(Context context, float pxValue) {
  197. final float scale = context.getResources().getDisplayMetrics().density;
  198. return (int) (pxValue / scale + 0.5f);
  199. }
  200. }
  201. 1
  202. 2
  203. 3
  204. 4
  205. 5
  206. 6
  207. 7
  208. 8
  209. 9
  210. 10
  211. 11
  212. 12
  213. 13
  214. 14
  215. 15
  216. 16
  217. 17
  218. 18
  219. 19
  220. 20
  221. 21
  222. 22
  223. 参考:
  224. [http://www.zhihu.com/question/33312136][http_www.zhihu.com_question_33312136]
  225. [http://www.zhihu.com/question/20697111][http_www.zhihu.com_question_20697111]

发表评论

表情:
评论列表 (有 0 条评论,72人围观)

还没有评论,来说两句吧...

相关阅读