一文搞懂Android中dp、sp与px的关系!

1.屏幕基础

先了解屏幕相关的基础概念:

  1. 屏幕尺寸屏幕对角线的实际物理尺寸。单位英寸(inch) ,1英寸 = 2.54厘米
  1. 屏幕像素数屏幕上水平和垂直方向上的像素点总数。通常以宽度(K)×高度(P)的形式表示,例如1920×1080 - 1080P, 2048 * 1080 - 2K , 4096×1080 - 4K。 平常说的 1080P 指的是高度占据1080个物理像素,而 2K 或者4K 指的是宽度占据一定数量的像素数,K表示等效像素,1个等效像素 = 1024个物理像素,一换算就出来了。

  2. 屏幕分辨率即屏幕密度, 单位dpi(dots per inch ,每英寸点数)或者ppi (pixels per inch ,每英寸像素数) ,两者一般等效,屏幕的清晰程度取决于屏幕分辨率,屏幕分辨率越高,每英寸展示的像素数越多,图像就越精细,而非唬人的像素数(什么2k、4k等)。

2.屏幕单位

  1. px物理像素,对应屏幕上的实际物理像素点。

  2. destiny屏幕密度,单位 dpi (dots per inch ,每英寸点数),注意和ppi (pixels per inch ,每英寸像素数) 区分,据网上资料显示,在屏幕显示领域,这两个值可以互换使用。即屏幕密度代表每英寸点数或者像素数!该值主要影响图像的显示精细度或者质量,因为每英寸的点数或者像素数越多,图像就越精细。 该值代表了屏幕的清晰度。

  3. dip(dp)密度无关像素,全称 densiny-independent pixels,这是Android系统中专门为了避免直接使用 px(物理像素)而造成的图像大小不同的情况。该值定义为等于屏幕密度为 160 dpi 的屏幕上的一个物理像素,系统会在运行时根据具体的屏幕密度对dp的大小进行缩放处理,因为不管是 dp 或者 sp 最终都会转换成 px。

  4. 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。后面会专门再出一篇讲解~

相关推荐
Estar.Lee2 小时前
查手机号归属地免费API接口教程
android·网络·后端·网络协议·tcp/ip·oneapi
温辉_xh3 小时前
uiautomator案例
android
工业甲酰苯胺4 小时前
MySQL 主从复制之多线程复制
android·mysql·adb
少说多做3434 小时前
Android 不同情况下使用 runOnUiThread
android·java
Estar.Lee6 小时前
时间操作[计算时间差]免费API接口教程
android·网络·后端·网络协议·tcp/ip
找藉口是失败者的习惯6 小时前
从传统到未来:Android XML布局 与 Jetpack Compose的全面对比
android·xml
Jinkey7 小时前
FlutterBasic - GetBuilder、Obx、GetX<Controller>、GetxController 有啥区别
android·flutter·ios
大白要努力!9 小时前
Android opencv使用Core.hconcat 进行图像拼接
android·opencv
天空中的野鸟10 小时前
Android音频采集
android·音视频
小白也想学C11 小时前
Android 功耗分析(底层篇)
android·功耗