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

相关推荐
秋96 分钟前
java中对操作mysql8.0.46与MySQL9.7.0有什么区别,并举例说明
android·java·adb
小书房22 分钟前
Kotlin协程的运行原理
android·开发语言·kotlin·协程
ooseabiscuit31 分钟前
Laravel10.x重磅发布:新特性全解析
android·java·开发语言·mysql
svdo1250p35 分钟前
“Fatal error: require(): Failed opening required...” 以及如何彻底避免它再次出现
android·ide·android studio
Digitally41 分钟前
如何将 POCO 手机同步到电脑?
android
赏金术士1 小时前
JetPack Compose 基础核心模块(一)
android·kotlin·android jetpack·compose
alexhilton9 小时前
如何用Perfetto来对启动优化去伪存真
android·kotlin·android jetpack
赏金术士10 小时前
Kotlin 从入门到进阶 之函数模块(核心基础)(二)
android·开发语言·kotlin
鱼儿也有烦恼12 小时前
8 issues were found when checking AAR metadata:
android