在Android中PX、DP(DIP)、SP、DPI、PPI的区别

本文探讨了Android中像素单位的区别,包括PX、DP(DIP)、SP的概念及其与DPI、PPI的关系。DP用于保持UI元素在不同屏幕密度上的显示一致性,SP是可缩放像素,常用于文字大小。屏幕密度(DPI/PPI)影响了单位转换,可能导致低密度屏幕上的元素显示过大。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在Android中PX、DP(DIP)、SP、DPI、PPI的区别

先说比较简单的,PX、DP(DIP)和SP。

PX的全称是Pixel,翻译过来是”像素“的意思,Pixel是由Picture和Element两个单词合并而来的,也就是图像的元素之意。
比较准确的定义是:像素是指由一个数字序列表示的图像中的一个最小单位。
一个数字图像就是一系列像素的集合,每个像素可以由各自的颜色值和具体的位置,通过对图像这样数字化表示,之后就可以被打印、传输或存储。
上面说的像素叫做逻辑像素,例如我们通过查看图片的属性可以看到该图片的尺寸是1080540,这里的1080540就是逻辑像素,也叫图像分辨率。而手机屏幕或显示器由一个个显示点组成,例如锤子 Pro2s的手机屏幕分辨率是2160*1080,这些显示点叫做物理像素,也叫显示分辨率。

问题:
1、将一张1080540的图片全屏显示到21601080的屏幕上会怎么样?
4个物理像素点显示一个逻辑像素,每个逻辑像素点的间距会比较大,在肉眼看来,图片就比较粗糙。

2、反过来,将一张21601080的图片显示到1080540的屏幕上又会怎么样?
4个逻辑像素点经过采样后,显示到一个物理像素点上。

**DP(DIP)**的全称是Density Independent Pixels,即密度无关像素。其中密度是屏幕像素密度,也就是每英寸显示的像素点数。我们在开发中使用dp,而不是px作为控件长度的单位,是为了在不同设备上保持显示一致的UI元素。在160dpi的设备上,1dp=1px。
例如:在5英寸,160dpi的手机上显示160dp长的线,就是160px的长度,换算成实际长度就是160/160 = 1 英寸。
在5英寸,320dpi的手机上显示160dp长的线,就是320px的长度,换算成实际长度也是320/320 = 1 英寸。
所以,这条线在不同屏幕密度的手机上显示效果就保持了一致。

那么问题来了,在3英寸,160dpi的手机上显示1dp的线,他的长度还是160/160 = 1英寸,但是却占用了屏幕1/3的空间,所以就会看起来比较大。

SP Scaled Pixels,可缩放像素,常用于文字大小的单位。和dp类似,但是可以跟随系统的设置的文字大小而缩放。

DPI全称是Dot Per Inch,每英寸包含的点,最早用于印刷行业,即一英寸打印的墨点数,用于打印的清晰度。

PPI全称是Pixel Per Inch,每英寸包含的像素,用于描述显示屏的屏幕密度,PPI越高,显示的图像越清晰。

因为在屏幕中,每个像素就是一个个的物理显示点来显示的,所以在Android系统中定义的DPI和手机厂商宣传的屏幕PPI是一个意思。我们可以通过DisplayMetrics类看到Android系统定义几种屏幕密度。

屏幕密度数值
低密度 ldpi120dpi
中密度 mdpi160dpi
高密度 hdpi240dpi
超高密度 xhdpi320dpi
超超高密度 xxhdpi480dpi
超超超高密度 xxxhdpi640dpi

在Android系统获取屏幕分辨率、屏幕密度、屏幕尺寸

        DisplayMetrics displayMetrics = new DisplayMetrics();
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1) {
            getWindowManager().getDefaultDisplay().getRealMetrics(displayMetrics);
        } else {
            getWindowManager().getDefaultDisplay().getMetrics(displayMetrics);
        }
        int height = displayMetrics.heightPixels;
        int width = displayMetrics.widthPixels;

        //屏幕分辨率,在4.2系统之前无法获取实际屏幕分辨率,因为还有状态栏和导航栏
        String screenResolution = width + "*" + height;
        //屏幕密度比例 当前屏幕密度与基准屏幕密度160dpi的比
        String density = String.valueOf(displayMetrics.density);
        //屏幕密度,是系统定义的屏幕密度种类之一,并不是实际屏幕密度
        String densityDpi = String.valueOf(displayMetrics.densityDpi) + "dpi";
        //横竖方向上的屏幕密度,这才是实际屏幕密度
        String densityDpiOrientation = displayMetrics.xdpi + ":" + displayMetrics.ydpi;
        //屏幕尺寸,屏幕对角线的长度
        String screenSize = String.va lueOf(Math.sqrt(Math.pow((width / displayMetrics.xdpi), 2) + Math.pow((height / displayMetrics.ydpi), 2)));
        //屏幕缩放密度,用于缩放文字
        String scaledDensity = String.valueOf(displayMetrics.scaledDensity);

问题:为什么在一些低屏幕密度的屏幕上显示的控件大小或间距,比高屏幕密度的屏幕上显示出来的还要更大一些。

在回答这个问题之前,我们要知道在xml布局文件中为控件设置的宽高或间距值(例10dp),是怎么把dp值转换为px值的?

// android.util.TypedValue

public static float applyDimension(int unit, float value,
                                       DisplayMetrics metrics)
    {
        switch (unit) {
        case COMPLEX_UNIT_PX:
            return value;
        case COMPLEX_UNIT_DIP:
            return value * metrics.density;
        case COMPLEX_UNIT_SP:
            return value * metrics.scaledDensity;
        case COMPLEX_UNIT_PT:
            return value * metrics.xdpi * (1.0f/72);
        case COMPLEX_UNIT_IN:
            return value * metrics.xdpi;
        case COMPLEX_UNIT_MM:
            return value * metrics.xdpi * (1.0f/25.4f);
        }
        return 0;
    }

获取xml像素值的getDimensionPixelSize方法最终会调用到TypedValue类的applyDimension方法中。可以看出,如果在布局中使用的单位是DIP(DP)的话,会将其值乘以当前的屏幕密度比率(当前屏幕密度/160),就得到了对应的像素值。而通过DisplayMetrics获取的density或densityDpi是Android系统框架事先定义好的几种值(详细见上表),但是实际屏幕的屏幕密度不一定与其保持一致。
前面已经说到屏幕实际DPI值,可以通过displayMetrics.xdpi和displayMetrics.ydpi获取。

所以结论就是在将dp转换成px时,参与计算的dpi值比实际屏幕dpi大,导致实际显示过大。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值