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

相关推荐
Zhu7585 小时前
在k8s集群部署MySQL单实例,支持多个主流发行版
android·mysql·kubernetes
AFinalStone8 小时前
Android 7系统异常问题排查(四)Framework层(上)—System Server Watchdog
android·系统异常
宝杰X79 小时前
Android Room3 多平台数据库
android·数据库
huibin14785236912 小时前
热缓解学习记录
android·学习
小田的博客15 小时前
SAP MM 供应商银行主数据更新报错!message R1228!
android·java·服务器
一笑的小酒馆16 小时前
Android智能猫砂盆视频加载慢卡顿问题分析
android
只会cv的小前端18 小时前
七巧低代码服务端脚本使用方法
android·低代码·rxjava
18 小时前
Android 自定义 View 实战:从零打造工业级全向摇杆控件(OmniJoystickView)
android·kotlin·自定义view·摇杆控件
雨白18 小时前
深入理解 Kotlin 协程 (十一):以逸待劳,探秘 select 多路复用与并发安全策略
android·kotlin
hunterandroid21 小时前
[Android 从零到一] Android 深度链接与 App Links:从 URI Scheme 到可验证的应用跳转
android