屏幕适配:dp、px、ppi、sp、手机尺寸和分辨率之间的关系

DisplayMetrics dm = new DisplayMetrics();
getWindowManager().getDefaultDisplay().getMetrics(dm);
int screenWidthPx = dm.widthPixels;
int screenHeighPx = dm.heightPixels;
int virtualKeyHeight = 0;
Resources res = getResources();
int resourceId = res.getIdentifier("navigation_bar_height", "dimen", "android");
if (resourceId > 0)
    virtualKeyHeight = res.getDimensionPixelSize(resourceId);
float density = getResources().getDisplayMetrics().density;
int screenWidthDp = (int) (screenWidthPx / density + 0.5f);
int screenHeighDp = (int) ((screenHeighPx + virtualKeyHeight) / density + 0.5f);
Log.i(TAG, "屏幕宽:" + screenWidthPx + "px,屏幕高:" + screenHeighPx + "px,虚拟键高:" + virtualKeyHeight + "px");
Log.i(TAG, "屏幕宽:" + screenWidthDp + "dp,屏幕高:" + screenHeighDp + "dp,density:" + density);
分别在三款手机上运行出的结果:
(1)荣耀8:主屏尺寸:5.2英寸。主屏分辨率:1920x1080像素
屏幕宽:1080px,屏幕高:1794px,虚拟键高:126px
屏幕宽:360dp,屏幕高:640dp,density:3.0
(2)E2:主屏尺寸:5.2英寸。主屏分辨率:1280x720像素
屏幕宽:720px,屏幕高:1184px,虚拟键高:96px
屏幕宽:360dp,屏幕高:640dp,density:2.0
(3)S9:主屏尺寸:英寸。主屏分辨率:1440x720像素
屏幕宽:720px,屏幕高:1344px,虚拟键高:96px

屏幕宽:360dp,屏幕高:720dp,density:2.0

(4):主屏尺寸:英寸。主屏分辨率:1280x640像素
屏幕宽:640px,屏幕高:1184px,虚拟键高:96px
屏幕宽:320dp,屏幕高:640dp,density:2.0


    手机屏幕的尺寸用屏幕显示区对角线的尺寸表示,一般用英寸作为单位。1英寸(in)=2.54    厘米(cm)。

    px其实所有的画面都是由一个个的小点组成的,这一个个的小点就称之为像素。 一块方形的屏幕横向有多少个点,竖向有多少个点,相乘之后的数值就是这块屏幕的像素。

    PPI = Pixels per inch,每英寸上的像素数,即 "像素密度"
    xhdpi: 2.0
    hdpi: 1.5
    mdpi: 1.0 (baseline)
    ldpi: 0.75
    Android系统定义了四种像素密度:低(120dpi)、中(160dpi)、高(240dpi)和超高(320dpi),它们对应的dp到px的系数分别为0.75、1、1.5和2(该系数乘dp长度即像素数)。例如界面上有一个长度为“80dp”的图片,那么它在240dpi的手机上实际显示为80x1.5=120px,在320dpi的手机上实际显示为80x2=160px。如果你拿这两部手机放在一起对比,会发现这个图片的物理尺寸一样大(120px除以240px/in结果为0.5in即0.5英寸,160px除以320px/in也是0.5英寸),这就是使用dp作为单位的效果。横向和纵向的每英寸像素数量值相同,因为大部分手机屏幕使用正方形的像素点。

    dip与dp完全相同,只是名字不同而已。在早期的Android版本里多使用dip,后来为了与sp统一就建议使用dp这个名字了。


    假设手机屏幕宽度是screenWidthIn英寸,手机屏幕宽有screenWidthPx个像素点,那么像素密度ppi为screenWidthPx  / screenWidthIn,所以手机屏幕宽的总dp值是160 x screenWidthPx / ppi即screenWidthIn x 160 。所以屏幕宽2英寸的手机宽320dp,1dp = 1/160英寸,以此类推。


    dp x ppi / 160 = px    ( ppi / 160即上面代码的density值,表示1dp有density个px )。

    sp x ppi / 160 = px

   


      按照像素密度等于每英寸的像素数的算法,将1280的平方和720的平方之和开方后,再除以5.2英寸,结果约等于282.4,并非density:2.0乘以160即320的结果。所以一般手机代码算出来的结果会是2.0x160、1.75x160、1.5x160、1x160等之间的数,不是精确的每英寸像素数。


    分辨率为1280x720像素(屏幕宽:360dp)的手机,可通过 adb shell wm size 640x1280 命令,改成了屏幕宽:320dp。此时手机上的效果会是:可见屏幕的物理尺寸变小。设置后输入如下结果:

    屏幕宽:640px,屏幕高:1184px,虚拟键高:96px
    屏幕宽:320dp,屏幕高:640dp,density:2.0


    也可以再设置回adb shell wm size 720x1280,通过adb shell wm density 360,改成了屏幕宽:320dp。方便测试不同尺寸的屏幕适配问题。此时手机上的效果会是:activity的内容会显示不全,最右边部分内容被挤出屏幕外。设置后输入如下结果:

    屏幕宽:720px,屏幕高:1184px,虚拟键高:108px
    屏幕宽:320dp,屏幕高:574dp,density:2.25


    输入命令adb shell dumpsys window displays或adb shell wm size会得到屏幕分辨率,dp值,虚拟键高度等。


    屏幕适配方法一,在app下的res下建立values-1184x640等不同分辨率的文件夹(本身是1280x640,按上述方法打印出来的屏幕高:1184px),再建dimens.xml文件,编写1280x640标准下的dp值。针对图片则建drawable-hdpi-1184x640等文件夹,放图片。

    屏幕适配方法二,在app下的res下建立values-sw320dp等文件夹(指1280x640px算下来的屏幕宽是320dp),再建dimens.xml文件,编写1280x640标准下的dp值。针对图片则建drawable-sw320dp-hdpi、drawable-sw320dp-xhdpi等文件夹,放图片。


    sp与缩放无关的抽象像素(Scale-independent Pixel)。sp和dp很类似但唯一的区别是,Android系统允许用户自定义文字尺寸大小(小、正常、大、超大等等),当文字尺寸是“正常”时,1sp=1dp=0.00625英寸,而当文字尺寸是“大”或“超大”时,1sp>1dp=1英寸/160dp=0.00625英寸。类似我们在windows里调整字体尺寸以后的效果——窗口大小不变,只有文字大小改变。

展开阅读全文

没有更多推荐了,返回首页