1.屏幕基础
先了解屏幕相关的基础概念:
- 屏幕尺寸 :屏幕对角线的实际物理尺寸。单位英寸(inch) ,1英寸 = 2.54厘米
-
屏幕像素数 :屏幕上水平和垂直方向上的像素点总数。通常以宽度(K)×高度(P)的形式表示,例如1920×1080 - 1080P, 2048 * 1080 - 2K , 4096×1080 - 4K。 平常说的 1080P 指的是高度占据1080个物理像素,而 2K 或者4K 指的是宽度占据一定数量的像素数,K表示等效像素,1个等效像素 = 1024个物理像素,一换算就出来了。
-
屏幕分辨率 :即屏幕密度, 单位dpi(dots per inch ,每英寸点数)或者ppi (pixels per inch ,每英寸像素数) ,两者一般等效,屏幕的清晰程度取决于屏幕分辨率,屏幕分辨率越高,每英寸展示的像素数越多,图像就越精细,而非唬人的像素数(什么2k、4k等)。
2.屏幕单位
-
px :
物理像素
,对应屏幕上的实际物理像素点。 -
destiny :
屏幕密度
,单位 dpi (dots per inch ,每英寸点数),注意和ppi (pixels per inch ,每英寸像素数) 区分,据网上资料显示,在屏幕显示领域,这两个值可以互换使用。即屏幕密度代表每英寸点数或者像素数!该值主要影响图像的显示精细度或者质量,因为每英寸的点数或者像素数越多,图像就越精细。 该值代表了屏幕的清晰度。 -
dip(dp) :
密度无关像素
,全称 densiny-independent pixels,这是Android系统中专门为了避免直接使用 px(物理像素)而造成的图像大小不同的情况。该值定义为等于屏幕密度为 160 dpi 的屏幕上的一个物理像素,系统会在运行时根据具体的屏幕密度对dp的大小进行缩放处理,因为不管是 dp 或者 sp 最终都会转换成 px。 -
sp :
放大像素(比例像素)
全称 scaled pixels-best for text size,同为Android系统中专用单位,和 dp 单位一般情况下相同,但可以根据用户配置的字体大小进行缩放。 用于字体的大小,切勿用于布局。
3.换算关系
1.由于 1 dp(密度无关像素) 定义为屏幕密度为 160 dpi 屏幕上的一个px(物理像素)
=> 我们可以得出基准屏幕密度为 160dpi = 160 ppi = 160 像素数/英寸 或者 点数/英寸
=> px = dp * (destiny / 160)
例如,一个屏幕密度为320dpi 的设备上,1dp等于多少实际的物理像素?
代入上述公式可得 1 * (320/160) = 2px,可以看出1dp 等于2px。
2.那在不同屏幕密度的手机屏幕上,相同的 dp 是否会造成不同的显示大小呢?
继续换算下,屏幕密度为160dpi的屏幕上,每个像素大小为 1/160 英寸, 1dp = 1px => 1/160 英寸,即1dp 对应1/160英寸。
当屏幕密度变为320dpi 时,每个像素大小为1/320英寸,1dp = 2px => 2 * 1/320 = 1/160 英寸,1dp 仍然对应1/160英寸。
所以相同 dp 在不同 destiny 的手机上, 仍然保持同样的大小,即dp/sp 屏蔽了不同屏幕密度设备上视图大小的差异。 如下图:
4.Android 设备中的 dp 与 sp
回到安卓手机中,设备不仅具有不同的屏幕尺寸(手机、平板电脑、电视等),而且具有不同像素尺寸的屏幕。一台设备的每英寸像素数可能为 160,而另一台设备在同一空间内可以容纳 480 像素。如果不考虑像素密度的这些变化,系统可能会缩放图片,导致图片模糊不清,或者图片可能以错误的尺寸显示。因此出现了dp和sp,屏蔽掉设备屏幕密度的差异。
可以看到,相同屏幕尺寸的手机,不同屏幕密度,通过使用密度无关像素(dp)展示的图片具有相同大小!
在 Android 设备中,通过 DisplayMetrics 度量系统获得的 destiny 实际上是设备的逻辑屏幕密度 ,该值为设备实际屏幕密度/160 ,我的手机输出的 DisplayMetrics.destiny
为3.0 (设备实际的屏幕密度 / 160),是超超高密度屏幕~
- 在低密度屏幕上,
DisplayMetrics.density
等于 0.75; - 在中密度屏幕上,
DisplayMetrics.density
等于 1.0; - 在高密度屏幕上,
DisplayMetrics.density
等于 1.5; - 在超高密度屏幕上,
DisplayMetrics.density
等于 2.0
php
/**
* The logical density of the display. This is a scaling factor for the
* Density Independent Pixel unit, where one DIP is one pixel on an
* approximately 160 dpi screen (for example a 240x320, 1.5"x2" screen),
* providing the baseline of the system's display. Thus on a 160dpi screen
* this density value will be 1; on a 120 dpi screen it would be .75; etc.
*
* <p>This value does not exactly follow the real screen size (as given by
* {@link #xdpi} and {@link #ydpi}, but rather is used to scale the size of
* the overall UI in steps based on gross changes in the display dpi. For
* example, a 240x320 screen will have a density of 1 even if its width is
* 1.8", 1.3", etc. However, if the screen resolution is increased to
* 320x480 but the screen size remained 1.5"x2" then the density would be
* increased (probably to 1.5).
*
* @see #DENSITY_DEFAULT
*/
public float density;
1.在 Android 中,设备的 dp 和 sp 与 px 的换算关系?
DisplayMetrics.density
代表设备的逻辑屏幕密度 ,而 DisplayMetrics.scaledDensity
代表设备字体逻辑缩放因子。
一般情况下 scaledDestiny = destiny ,但保不好用户会进行调整字体大小或者显示大小,导致scaledDestiny > destiny 或者 scaledDestiny < destiny,因此字体会按照scaledDestiny进行缩放。
dp 和 px换算关系: px = dp * DisplayMetrics.density
sp 和 px换算关系: px = sp * DisplayMetrics.scaledDensity
dp 和 sp 换算关系:dp:sp = DisplayMetrics.scaledDensity: DisplayMetrics.density
2.如下图,如果更改系统字体大小后,想保持应用的字体不变怎么办?
系统字体大小只影响 scaledDestiny,不影响 destiny。
可以在 sp 转 dp 时,不使用 DisplayMetrics.scaledDestiny,而是自定义转换,比如使用DisplayMetrics.destiny;或者干脆直接使用 dp 的单位。
3.如下图,如果更改系统显示大小后,想保持应用的字体不变怎么办?
系统显示大小不只影响 scaledDestiny,还影响 destiny。后面会专门再出一篇讲解~